23 #ifndef REFL_INCLUDE_HPP
24 #define REFL_INCLUDE_HPP
32 #include <type_traits>
42 #pragma warning( disable : 4003
)
45 #if defined(__clang__
)
46 #if __has_feature
(cxx_rtti)
47 #define REFL_RTTI_ENABLED
49 #elif defined(__GNUG__)
50 #if defined(__GXX_RTTI)
51 #define REFL_RTTI_ENABLED
53 #elif defined(_MSC_VER)
55 #define REFL_RTTI_ENABLED
90 #define REFL_MAKE_CONST_STRING(CString)
91 (::refl::util::detail::copy_from_unsized<::refl::util::detail::strlen(CString)>(CString))
107 static constexpr size_t npos =
static_cast<size_t>(-1);
110 static constexpr size_t size = N;
120 constexpr const_string()
noexcept
128 constexpr const_string(
const const_string<N>& other)
noexcept
129 : const_string(other, std::make_index_sequence<N>())
136 constexpr const_string(
const char(&data)[N + 1])
noexcept
137 : const_string(data, std::make_index_sequence<N>())
144 explicit constexpr operator
const char*()
const noexcept
152 explicit operator std::string()
const noexcept
160 constexpr const char* c_str()
const noexcept
168 std::string str()
const noexcept
181 template <size_t Pos, size_t Count = npos>
182 constexpr auto substr()
const noexcept
184 static_assert(Pos <= N);
185 constexpr size_t NewSize = (std::min)(Count, N - Pos);
187 char buf[NewSize + 1]{};
188 for (size_t i = 0; i < NewSize; i++) {
189 buf[i] = data[Pos + i];
192 return const_string<NewSize>(buf);
203 constexpr auto find(
char ch, size_t pos = 0)
const noexcept
205 for (size_t i = pos; i < N; i++) {
221 constexpr auto rfind(
char ch, size_t pos = npos)
const noexcept
223 for (size_t i = (pos == npos ? N - 1 : pos); i + 1 > 0; i--) {
236 template <size_t... Idx>
237 constexpr const_string(
const const_string<N>& other, std::index_sequence<Idx...>)
noexcept
238 : data{ other.data[Idx]... }
245 template <size_t... Idx>
246 constexpr const_string(
const char(&data)[
sizeof...(Idx) + 1], std::index_sequence<Idx...>)
noexcept
247 : data{ data[Idx]... }
258 constexpr const_string<0> make_const_string()
noexcept
269 constexpr const_string<N - 1> make_const_string(
const char(&str)[N])
noexcept
279 constexpr const_string<1> make_const_string(
char ch)
noexcept
281 const char str[2]{ ch,
'\0' };
282 return make_const_string(str);
290 template <size_t N, size_t M>
291 constexpr const_string<N + M> operator+(
const const_string<N>& a,
const const_string<M>& b)
noexcept
293 char data[N + M + 1] { };
294 for (size_t i = 0; i < N; i++)
296 for (size_t i = 0; i < M; i++)
297 data[N + i] = b.data[i];
306 template <size_t N, size_t M>
307 constexpr const_string<N + M - 1> operator+(
const const_string<N>& a,
const char(&b)[M])
noexcept
309 return a + make_const_string(b);
317 template <size_t N, size_t M>
318 constexpr const_string<N + M - 1> operator+(
const char(&a)[N],
const const_string<M>& b)
noexcept
320 return make_const_string(a) + b;
328 template <size_t N, size_t M>
329 constexpr bool operator==(
const const_string<N>& a,
const const_string<M>& b)
noexcept
331 if constexpr (N != M) {
335 for (size_t i = 0; i < M; i++) {
336 if (a.data[i] != b.data[i]) {
349 template <size_t N, size_t M>
350 constexpr bool operator!=(
const const_string<N>& a,
const const_string<M>& b)
noexcept
360 template <size_t N, size_t M>
361 constexpr bool operator==(
const const_string<N>& a,
const char(&b)[M])
noexcept
363 return a == make_const_string(b);
371 template <size_t N, size_t M>
372 constexpr bool operator!=(
const const_string<N>& a,
const char(&b)[M])
noexcept
374 return a != make_const_string(b);
382 template <size_t N, size_t M>
383 constexpr bool operator==(
const char(&a)[N],
const const_string<M>& b)
noexcept
385 return make_const_string(a) == b;
393 template <size_t N, size_t M>
394 constexpr bool operator!=(
const char(&a)[N],
const const_string<M>& b)
noexcept
396 return make_const_string(a) != b;
400 constexpr std::ostream& operator<<(std::ostream& os,
const const_string<N>& str)
noexcept
402 return os << str.c_str();
407 constexpr size_t strlen(
const char*
const str)
409 return *str ? 1 + strlen(str + 1) : 0;
413 constexpr const_string<N> copy_from_unsized(
const char*
const str)
415 const_string<N> cstr;
416 for (size_t i = 0; i < N; i++) {
417 cstr.data[i] = str[i];
441 template <
typename... Ts>
445 static constexpr intptr_t size =
sizeof...(Ts);
448 template <
typename T>
452 static constexpr intptr_t size = 1;
455 template <
typename T>
456 using type_tag = type_list<T>;
460 using util::const_string;
461 using util::make_const_string;
462 using util::type_list;
463 using util::type_tag;
472 namespace macro_exports
491 using namespace refl::detail::macro_exports;
505 template <
typename T>
509 struct invalid_marker{};
514 template <size_t,
typename>
518 static constexpr size_t member_count{ 0 };
521 static constexpr refl::const_string<0> name{
"" };
524 static constexpr std::tuple<> attributes{ };
530 template <
typename T>
531 struct type_info__<
const T> :
public type_info__<T> {};
536 template <
typename T>
537 struct type_info__<
volatile T> :
public type_info__<T> {};
542 template <
typename T>
543 struct type_info__<
const volatile T> :
public type_info__<T> {};
553 template <
typename T>
554 using type_info = refl_impl::metadata::type_info__<T>;
556 template <
typename T, size_t N>
557 using member_info =
typename type_info<T>::
template member<N>;
588 class type_descriptor;
590 template <
typename, size_t>
591 class field_descriptor;
593 template <
typename, size_t>
594 class function_descriptor;
609 template <
typename T>
610 struct remove_qualifiers
612 typedef std::remove_cv_t<std::remove_reference_t<T>> type;
620 template <
typename T>
621 using remove_qualifiers_t =
typename remove_qualifiers<T>::type;
626 template <
typename T>
627 decltype(
typename refl::detail::type_info<T>::invalid_marker{}, std::false_type{}) is_reflectable_test(
int);
630 template <
typename T>
631 std::true_type is_reflectable_test(...);
642 template <
typename T>
643 struct is_reflectable :
decltype(detail::is_reflectable_test<T>(0))
653 template <
typename T>
654 [[maybe_unused]]
static constexpr bool is_reflectable_v{ is_reflectable<T>::value };
659 template <
typename U>
660 [[maybe_unused]]
static auto is_container_test(
int) ->
decltype(std::declval<U>().begin(), std::declval<U>().end(), std::true_type{});
663 template <
typename U>
664 [[maybe_unused]]
static std::false_type is_container_test(...);
670 template <
typename T>
671 struct is_container :
decltype(detail::is_container_test<T>(0))
678 template <
typename T>
679 [[maybe_unused]]
static constexpr bool is_container_v{ is_container<T>::value };
684 template <size_t D, size_t N,
typename... Ts>
687 template <size_t D, size_t N>
690 static_assert(N > 0,
"Missing arguments list for get<N, Ts...>!");
693 template <size_t N,
typename T,
typename... Ts>
694 struct get<1, N, T, Ts...> :
public get<
695 (N > 16 ? (N > 64 ? 64 : 16) : 1),
700 template <
typename T,
typename... Ts>
701 struct get<1, 0, T, Ts...>
706 template <
typename T,
typename... Ts>
707 struct get<16, 0, T, Ts...>
712 template <
typename T,
typename... Ts>
713 struct get<64, 0, T, Ts...>
719 size_t N,
typename T0,
typename T1,
typename T2,
typename T3,
720 typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
721 typename T9,
typename T10,
typename T11,
typename T12,
722 typename T13,
typename T14,
typename T15,
typename... Ts>
724 16, N, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
725 T13, T14, T15, Ts...> : get<1, N - 16, Ts...>
730 size_t N,
typename T0,
typename T1,
typename T2,
typename T3,
731 typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
732 typename T9,
typename T10,
typename T11,
typename T12,
733 typename T13,
typename T14,
typename T15,
typename T16,
734 typename T17,
typename T18,
typename T19,
typename T20,
735 typename T21,
typename T22,
typename T23,
typename T24,
736 typename T25,
typename T26,
typename T27,
typename T28,
737 typename T29,
typename T30,
typename T31,
typename T32,
738 typename T33,
typename T34,
typename T35,
typename T36,
739 typename T37,
typename T38,
typename T39,
typename T40,
740 typename T41,
typename T42,
typename T43,
typename T44,
741 typename T45,
typename T46,
typename T47,
typename T48,
742 typename T49,
typename T50,
typename T51,
typename T52,
743 typename T53,
typename T54,
typename T55,
typename T56,
744 typename T57,
typename T58,
typename T59,
typename T60,
745 typename T61,
typename T62,
typename T63,
typename... Ts>
747 64, N, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
748 T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
749 T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38,
750 T39, T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50, T51,
751 T52, T53, T54, T55, T56, T57, T58, T59, T60, T61, T62, T63,
752 Ts...> : get<1, N - 64, Ts...>
756 template <size_t N,
typename...>
759 template <size_t N,
typename T,
typename... Ts>
760 struct skip<N, T, Ts...> : skip<N - 1, Ts...>
764 template <
typename T,
typename... Ts>
765 struct skip<0, T, Ts...>
767 typedef type_list<T, Ts...> type;
773 typedef type_list<> type;
778 template <size_t,
typename>
790 template <size_t N,
typename... Ts>
791 struct get<N, type_list<Ts...>> : detail::get<1, N, Ts...>
799 template <size_t N,
typename TypeList>
800 using get_t =
typename get<N, TypeList>::type;
803 template <size_t,
typename>
815 template <size_t N,
typename... Ts>
816 struct skip<N, type_list<Ts...>> : detail::skip<N, Ts...>
824 template <size_t N,
typename TypeList>
825 using skip_t =
typename skip<N, TypeList>::type;
840 template <
template <
typename...>
typename T,
typename... Ts>
841 struct as_type_list<T<Ts...>>
843 typedef type_list<Ts...> type;
847 template <
typename T>
848 struct as_type_list : as_type_list<remove_qualifiers_t<T>>
858 template <
typename T>
859 using as_type_list_t =
typename as_type_list<T>::type;
874 template <
template <
typename...>
typename T,
typename... Ts>
875 struct as_tuple<T<Ts...>>
877 typedef std::tuple<Ts...> type;
881 template <
typename T>
882 struct as_tuple : as_tuple<remove_qualifiers_t<T>>
892 template <
typename T>
893 using as_tuple_t =
typename as_tuple<T>::type;
898 template <
typename TypeList>
899 using first = get<0, TypeList>;
905 template <
typename TypeList>
906 using first_t =
typename first<TypeList>::type;
911 template <
typename TypeList>
912 using last = get<TypeList::size - 1, TypeList>;
918 template <
typename TypeList>
919 using last_t =
typename last<TypeList>::type;
924 template <
typename TypeList>
925 using tail = skip<1, TypeList>;
931 template <
typename TypeList>
932 using tail_t =
typename tail<TypeList>::type;
936 template <
typename, size_t,
typename>
939 template <
typename... Us>
940 struct take<type_list<Us...>, 0, type_list<>>
942 using type = type_list<Us...>;
945 template <
typename... Us,
typename T,
typename... Ts>
946 struct take<type_list<Us...>, 0, type_list<T, Ts...>>
948 using type = type_list<Us...>;
951 template <size_t N,
typename... Us,
typename T,
typename... Ts>
952 struct take<type_list<Us...>, N, type_list<T, Ts...>>
954 using type =
typename take<type_list<Us..., T>, N - 1, type_list<Ts...>>::type;
961 template <size_t N,
typename TypeList>
962 using take = detail::take<type_list<>, N, TypeList>;
967 template <size_t N,
typename TypeList>
968 using take_t =
typename take<N, TypeList>::type;
973 template <
typename TypeList>
974 using init = take<TypeList::size - 1, TypeList>;
980 template <
typename TypeList>
981 using init_t =
typename init<TypeList>::type;
985 template <
typename,
typename>
988 template <
typename... Us>
989 struct reverse_impl<type_list<Us...>, type_list<>>
991 using type = type_list<Us...>;
994 template <
typename... Us,
typename T,
typename... Ts>
995 struct reverse_impl<type_list<Us...>, type_list<T, Ts...>>
997 using type =
typename reverse_impl<type_list<T, Us...>, type_list<Ts...>>::type;
1008 template <
typename TypeList>
1009 struct reverse : detail::reverse_impl<type_list<>, TypeList>
1017 template <
typename TypeList>
1018 using reverse_t =
typename reverse<TypeList>::type;
1027 template <
typename...>
1034 using type = type_list<>;
1038 template <
typename... Ts>
1039 struct concat<type_list<Ts...>>
1041 using type = type_list<Ts...>;
1048 template <
typename... Ts,
typename... Us>
1049 struct concat<type_list<Ts...>, type_list<Us...>>
1051 using type = type_list<Ts..., Us...>;
1058 template <
typename TypeList1,
typename TypeList2,
typename... TypeLists>
1059 struct concat<TypeList1, TypeList2, TypeLists...> : concat<
typename concat<TypeList1, TypeList2>::type, TypeLists...>
1067 template <
typename... Ts>
1068 using concat_t =
typename concat<Ts...>::type;
1073 template <
typename T,
typename TypeList>
1074 struct append : concat<TypeList, type_list<T>>
1082 template <
typename T,
typename TypeList>
1083 using append_t =
typename append<T, TypeList>::type;
1085 template <
typename,
typename>
1091 template <
typename T,
typename TypeList>
1092 struct prepend : concat<type_list<T>, TypeList>
1100 template <
typename T,
typename TypeList>
1101 using prepend_t =
typename prepend<T, TypeList>::type;
1105 template <
template<
typename>
typename,
typename...>
1108 template <
template<
typename>
typename Predicate>
1109 struct filter_impl<Predicate>
1111 using type = type_list<>;
1114 template <
template<
typename>
typename Predicate,
typename Head,
typename... Tail>
1115 struct filter_impl<Predicate, Head, Tail...>
1117 using type = std::conditional_t<Predicate<Head>::value,
1118 prepend_t<Head,
typename filter_impl<Predicate, Tail...>::type>,
1119 typename filter_impl<Predicate, Tail...>::type
1123 template <
template<
typename>
typename,
typename...>
1126 template <
template<
typename>
typename Mapper>
1127 struct map_impl<Mapper>
1129 using type = type_list<>;
1132 template <
template<
typename>
typename Mapper,
typename Head,
typename ...Tail>
1133 struct map_impl<Mapper, Head, Tail...>
1135 using type =
typename prepend<
typename Mapper<Head>::type,
1136 typename map_impl<Mapper, Tail...>::type>::type;
1141 template <
template<
typename>
typename,
typename>
1151 template <
template<
typename>
typename Predicate,
typename... Ts>
1152 struct filter<Predicate, type_list<Ts...>>
1154 using type =
typename detail::filter_impl<Predicate, Ts...>::type;
1162 template <
template<
typename>
typename Predicate,
typename TypeList>
1163 using filter_t =
typename filter<Predicate, TypeList>::type;
1166 template <
template<
typename>
typename,
typename>
1176 template <
template<
typename>
typename Mapper,
typename... Ts>
1177 struct map<Mapper, type_list<Ts...>>
1179 using type =
typename detail::map_impl<Mapper, Ts...>::type;
1187 template <
template<
typename>
typename Mapper,
typename... Ts>
1188 using map_t =
typename map<Mapper, Ts...>::type;
1192 template <
typename T>
1193 struct is_instance :
public std::false_type {};
1195 template <
template<
typename...>
typename T,
typename... Args>
1196 struct is_instance<T<Args...>> :
public std::true_type {};
1208 template <
typename T>
1209 struct is_instance : detail::is_instance<T>
1217 template <
typename T>
1218 [[maybe_unused]]
static constexpr bool is_instance_v{ is_instance<T>::value };
1226 template <
typename T,
template<
typename...>
typename U,
typename... Args>
1227 struct is_same_template
1229 template <
template<
typename...>
typename V,
typename = V<Args...>>
1230 static auto test(
int) -> std::is_same<V<Args...>, T>;
1232 template <
template<
typename...>
typename V>
1233 static std::false_type test(...);
1235 static constexpr bool value{
decltype(test<U>(0))::value};
1238 template <
template<
typename...>
typename T,
typename U>
1239 struct is_instance_of :
public std::false_type {};
1241 template <
template<
typename...>
typename T,
template<
typename...>
typename U,
typename... Args>
1242 struct is_instance_of<T, U<Args...>> :
public is_same_template<U<Args...>, T, Args...>
1257 template <
template<
typename...>
typename T,
typename U>
1258 struct is_instance_of : detail::is_instance_of<T, std::remove_cv_t<U>>
1266 template <
template<
typename...>
typename T,
typename U>
1267 [[maybe_unused]]
static constexpr bool is_instance_of_v{ is_instance_of<T, U>::value };
1270 template <
typename,
typename>
1282 template <
typename T,
typename... Ts>
1283 struct contains<T, type_list<Ts...>> : std::disjunction<std::is_same<std::remove_cv_t<T>, std::remove_cv_t<Ts>>...>
1291 template <
typename T,
typename TypeList>
1292 [[maybe_unused]]
static constexpr bool contains_v = contains<T, TypeList>::value;
1295 template <
template<
typename...>
typename,
typename>
1296 struct contains_instance;
1307 template <
template<
typename...>
typename T,
typename... Ts>
1308 struct contains_instance<T, type_list<Ts...>> : std::disjunction<trait::is_instance_of<T, std::remove_cv_t<Ts>>...>
1316 template <
template<
typename...>
typename T,
typename TypeList>
1317 [[maybe_unused]]
static constexpr bool contains_instance_v = contains_instance<T, TypeList>::value;
1320 template <
typename,
typename>
1321 struct contains_base;
1335 template <
typename T,
typename... Ts>
1336 struct contains_base<T, type_list<Ts...>> : std::disjunction<std::is_base_of<std::remove_cv_t<T>, std::remove_cv_t<Ts>>...>
1344 template <
typename T,
typename TypeList>
1345 [[maybe_unused]]
static constexpr bool contains_base_v = contains_base<T, TypeList>::value;
1349 template <
typename T, ptrdiff_t N,
typename... Ts>
1350 constexpr ptrdiff_t index_of()
noexcept
1352 if constexpr (
sizeof...(Ts) <= N)
return -1;
1353 else if constexpr (std::is_same_v<T, trait::get_t<N, type_list<Ts...>>>)
return N;
1354 else return index_of<T, N + 1, Ts...>();
1357 template <
typename T, ptrdiff_t N,
typename... Ts>
1358 constexpr ptrdiff_t index_of_base()
noexcept
1360 if constexpr (
sizeof...(Ts) <= N)
return -1;
1361 else if constexpr (std::is_base_of_v<T, trait::get_t<N, type_list<Ts...>>>)
return N;
1362 else return index_of_base<T, N + 1, Ts...>();
1365 template <
template<
typename...>
typename T, ptrdiff_t N,
typename... Ts>
1366 constexpr ptrdiff_t index_of_instance()
noexcept
1368 if constexpr (
sizeof...(Ts) <= N)
return -1;
1369 else if constexpr (is_instance_of_v<T, trait::get_t<N, type_list<Ts...>>>)
return N;
1370 else return index_of_instance<T, N + 1, Ts...>();
1375 template <
template<
typename...>
typename T, ptrdiff_t N,
typename... Ts>
1376 static constexpr ptrdiff_t index_of_instance_v = index_of_instance<T, N, Ts...>();
1380 template <
typename,
typename>
1387 template <
typename T,
typename... Ts>
1388 struct index_of<T, type_list<Ts...>> : std::integral_constant<ptrdiff_t, detail::index_of<T, 0, Ts...>()>
1396 template <
typename T,
typename TypeList>
1397 static constexpr ptrdiff_t index_of_v = index_of<T, TypeList>::value;
1400 template <
typename,
typename>
1401 struct index_of_base;
1407 template <
typename T,
typename... Ts>
1408 struct index_of_base<T, type_list<Ts...>> : std::integral_constant<ptrdiff_t, detail::index_of_base<T, 0, Ts...>()>
1416 template <
typename T,
typename TypeList>
1417 static constexpr ptrdiff_t index_of_base_v = index_of_base<T, TypeList>::value;
1420 template <
template<
typename...>
typename,
typename>
1421 struct index_of_instance;
1427 template <
template<
typename...>
typename T,
typename... Ts>
1428 struct index_of_instance<T, type_list<Ts...>> : std::integral_constant<ptrdiff_t, detail::index_of_instance_v<T, 0, Ts...>>
1436 template <
template<
typename...>
typename T,
typename TypeList>
1437 static constexpr ptrdiff_t index_of_instance_v = index_of_instance<T, TypeList>::value;
1441 template <
typename,
typename>
1444 template <
typename UniqueList>
1445 struct unique_impl<UniqueList, type_list<>>
1447 using type = UniqueList;
1450 template <
typename UniqueList,
typename T,
typename... Ts>
1451 struct unique_impl<UniqueList, type_list<T, Ts...>> :
1452 std::conditional_t<contains_v<T, UniqueList>,
1453 unique_impl<UniqueList, type_list<Ts...>>,
1454 unique_impl<append_t<T, UniqueList>, type_list<Ts...>>>
1466 template <
typename T>
1467 struct unique : detail::unique_impl<type_list<>, T>
1474 template <
typename T>
1475 using unique_t =
typename unique<T>::type;
1485 template <
typename T =
int,
typename... Ts>
1486 constexpr int ignore(Ts&&...)
noexcept
1495 template <
typename T>
1496 constexpr decltype(
auto) identity(T&& t)
noexcept
1498 return std::forward<T>(t);
1504 template <
typename T>
1505 constexpr const T& make_const(
const T& value)
noexcept
1513 template <
typename T>
1514 constexpr const T& make_const(T& value)
noexcept
1524 template <
typename T,
typename... Ts>
1525 constexpr std::array<T,
sizeof...(Ts)> to_array(
const std::tuple<Ts...>& tuple)
noexcept
1527 return std::apply([](
auto&& ... args) -> std::array<T,
sizeof...(Ts)> {
return { std::forward<
decltype(args)>(args)... }; }, tuple);
1534 template <
typename T>
1535 constexpr std::array<T, 0> to_array(
const std::tuple<>&)
noexcept
1542 template <
typename T, size_t... Idx>
1543 constexpr auto to_tuple([[maybe_unused]]
const std::array<T,
sizeof...(Idx)>& array, std::index_sequence<Idx...>)
noexcept
1545 if constexpr (
sizeof...(Idx) == 0)
return std::tuple<>{};
1546 else return std::make_tuple(std::get<Idx>(array)...);
1553 template <
typename T, size_t N>
1554 constexpr auto to_tuple(
const std::array<T, N>& array)
noexcept
1556 return detail::to_tuple<T>(array, std::make_index_sequence<N>{});
1563 template <
typename... Ts>
1564 constexpr std::tuple<Ts...> as_tuple(type_list<Ts...>)
noexcept
1566 static_assert((... && std::is_trivial_v<Ts>),
"Non-trivial types in type_list as not allowed!");
1573 template <
typename... Ts>
1574 constexpr type_list<Ts...> as_type_list(
const std::tuple<Ts...>&)
noexcept
1581 template <
typename F,
typename T>
1582 constexpr auto invoke_optional_index(F&& f, T&& t, size_t idx,
int) ->
decltype(f(std::forward<T>(t), idx))
1584 return f(std::forward<T>(t), idx);
1587 template <
typename F,
typename T>
1588 constexpr auto invoke_optional_index(F&& f, T&& t, size_t, ...) ->
decltype(f(std::forward<T>(t)))
1590 return f(std::forward<T>(t));
1593 template <
typename F,
typename... Carry>
1594 constexpr auto eval_in_order_to_tuple(type_list<>, std::index_sequence<>, F&&, Carry&&... carry)
1596 if constexpr (
sizeof...(Carry) == 0)
return std::tuple<>{};
1597 else return std::make_tuple(std::forward<Carry>(carry)...);
1604 template <
typename F,
typename T,
typename... Ts, size_t I, size_t... Idx,
typename... Carry>
1605 constexpr auto eval_in_order_to_tuple(type_list<T, Ts...>, std::index_sequence<I, Idx...>, F&& f, Carry&&... carry)
1607 static_assert(std::is_trivial_v<T>,
"Argument is a non-trivial type!");
1609 auto&& result = invoke_optional_index(f, T{}, I, 0);
1610 return eval_in_order_to_tuple(
1612 std::index_sequence<Idx...>{},
1614 std::forward<Carry>(carry)...,
1615 std::forward<
decltype(result)>(result)
1619 template <
typename F>
1620 constexpr void eval_in_order(type_list<>, std::index_sequence<>, [[maybe_unused]]F&& f)
1627 template <
typename F,
typename T,
typename... Ts, size_t I, size_t... Idx>
1628 constexpr void eval_in_order(type_list<T, Ts...>, std::index_sequence<I, Idx...>, F&& f)
1630 static_assert(std::is_trivial_v<T>,
"Argument is a non-trivial type!");
1632 invoke_optional_index(f, T{}, I, 0);
1633 return eval_in_order(
1635 std::index_sequence<Idx...>{},
1652 template <
typename F,
typename... Ts>
1653 constexpr auto map_to_tuple(type_list<Ts...> list, F&& f)
1655 return detail::eval_in_order_to_tuple(list, std::make_index_sequence<
sizeof...(Ts)>{}, std::forward<F>(f));
1669 template <
typename T,
typename F,
typename... Ts>
1670 constexpr auto map_to_array(type_list<Ts...> list, F&& f)
1672 return to_array<T>(map_to_tuple(list, std::forward<F>(f)));
1685 template <
typename F,
typename... Ts>
1686 constexpr void for_each(type_list<Ts...> list, F&& f)
1688 detail::eval_in_order(list, std::make_index_sequence<
sizeof...(Ts)>{}, std::forward<F>(f));
1695 template <
typename R,
typename F,
typename... Ts>
1696 constexpr R accumulate(type_list<>, F&&, R&& initial_value)
1698 return std::forward<R>(initial_value);
1707 template <
typename R,
typename F,
typename T,
typename... Ts>
1708 constexpr auto accumulate(type_list<T, Ts...>, F&& f, R&& initial_value)
1710 static_assert(std::is_trivial_v<T>,
"Argument is a non-trivial type!");
1712 return accumulate(type_list<Ts...> {},
1714 std::forward<std::invoke_result_t<F&&, R&&, T&&>>(
1715 f(std::forward<R>(initial_value), T {})));
1723 template <
typename F,
typename... Ts>
1724 constexpr size_t count_if(type_list<Ts...> list, F&& f)
1726 return accumulate<size_t>(list,
1727 [&](size_t acc,
const auto& t) -> size_t {
return acc + (f(t) ? 1 : 0); },
1733 template <
typename,
bool...>
1737 struct apply_mask<type_list<>>
1739 using type = type_list<>;
1742 template <
typename T,
typename... Ts,
bool... Bs>
1743 struct apply_mask<type_list<T, Ts...>,
true, Bs...>
1745 static_assert(std::is_trivial_v<T>,
"Argument is a non-trivial type!");
1746 using type = trait::prepend_t<T,
typename apply_mask<type_list<Ts...>, Bs...>::type>;
1749 template <
typename T,
typename... Ts,
bool... Bs>
1750 struct apply_mask<type_list<T, Ts...>,
false, Bs...> : apply_mask<type_list<Ts...>, Bs...>
1752 static_assert(std::is_trivial_v<T>,
"Argument is a non-trivial type!");
1755 template <
typename F,
typename... Ts>
1756 constexpr auto filter([[maybe_unused]] F f, type_list<Ts...>)
1758 return typename apply_mask<type_list<Ts...>, f(Ts{})...>::type{};
1773 template <
typename F,
typename... Ts>
1774 constexpr auto filter(type_list<Ts...> list, F&& f)
1776 return decltype(detail::filter(std::forward<F>(f), list))();
1783 template <
typename F,
typename... Ts>
1784 constexpr auto find_first(type_list<Ts...> list, F&& f)
1786 using result_list =
decltype(detail::filter(std::forward<F>(f), list));
1787 static_assert(result_list::size != 0,
"find_first did not match anything!");
1788 return trait::get_t<0, result_list>{};
1796 template <
typename F,
typename... Ts>
1797 constexpr auto find_one(type_list<Ts...> list, F&& f)
1799 using result_list =
decltype(detail::filter(std::forward<F>(f), list));
1800 static_assert(result_list::size != 0,
"find_one did not match anything!");
1801 static_assert(result_list::size == 1,
"Cannot resolve multiple matches in find_one!");
1802 return trait::get_t<0, result_list>{};
1809 template <
typename F,
typename... Ts>
1810 constexpr bool contains(type_list<Ts...> list, F&& f)
1812 using result_list =
decltype(detail::filter(std::forward<F>(f), list));
1813 return result_list::size > 0;
1820 template <
typename T,
typename... Ts>
1821 constexpr bool contains(type_list<Ts...>)
1823 return trait::contains_v<T, type_list<Ts...>>;
1830 template <
typename T,
typename... Ts>
1831 constexpr bool contains_base(
const std::tuple<Ts...>&)
1833 return trait::contains_base_v<T, type_list<Ts...>>;
1840 template <
template <
typename...>
typename T,
typename... Ts>
1841 constexpr bool contains_instance(
const std::tuple<Ts...>&)
1843 return trait::contains_instance_v<T, type_list<Ts...>>;
1856 template <
typename... Ts,
typename F>
1857 constexpr auto apply(type_list<Ts...>, F&& f)
1863 template <size_t N,
typename... Ts>
1864 constexpr auto& get(std::tuple<Ts...>& ts)
noexcept
1866 return std::get<N>(ts);
1870 template <size_t N,
typename... Ts>
1871 constexpr const auto& get(
const std::tuple<Ts...>& ts)
noexcept
1873 return std::get<N>(ts);
1877 template <
typename T,
typename... Ts>
1878 constexpr T& get(std::tuple<Ts...>& ts)
noexcept
1880 return std::get<T>(ts);
1884 template <
typename T,
typename... Ts>
1885 constexpr const T& get(
const std::tuple<Ts...>& ts)
noexcept
1887 return std::get<T>(ts);
1891 template <
template<
typename...>
typename T,
typename... Ts>
1892 constexpr auto& get_instance(std::tuple<Ts...>& ts)
noexcept
1894 static_assert((... || trait::is_instance_of_v<T, Ts>),
"The tuple does not contain a type that is a template instance of T!");
1895 constexpr size_t idx =
static_cast<size_t>(trait::index_of_instance_v<T, type_list<Ts...>>);
1896 return std::get<idx>(ts);
1900 template <
template<
typename...>
typename T,
typename... Ts>
1901 constexpr const auto& get_instance(
const std::tuple<Ts...>& ts)
noexcept
1903 static_assert((... || trait::is_instance_of_v<T, Ts>),
"The tuple does not contain a type that is a template instance of T!");
1904 constexpr size_t idx =
static_cast<size_t>(trait::index_of_instance_v<T, type_list<Ts...>>);
1905 return std::get<idx>(ts);
1915 template <
typename... Ts>
1916 constexpr type_list<descriptor::type_descriptor<Ts>...> reflect_types(type_list<Ts...>)
noexcept
1928 template <
typename... Ts>
1929 constexpr type_list<Ts...> unreflect_types(type_list<descriptor::type_descriptor<Ts>...>)
noexcept
1984 struct member :
public function,
public field{};
1990 struct any :
public member,
public type {};
1997 struct property :
public usage::function
1999 const std::optional<
const char*> friendly_name;
2001 constexpr property()
noexcept
2006 constexpr property(
const char* friendly_name)
noexcept
2007 : friendly_name(friendly_name)
2015 template <
typename F>
2016 struct debug :
public usage::any
2020 constexpr debug(F write)
2029 template <
typename... Ts>
2030 struct base_types : usage::type
2033 typedef type_list<Ts...> list_type;
2036 static constexpr list_type list{ };
2042 template <
typename... Ts>
2043 [[maybe_unused]]
static constexpr base_types<Ts...> bases{ };
2049 namespace macro_exports
2051 using attr::property;
2061 template <
typename T>
2062 auto member_type_test(
int) ->
decltype(
typename T::member_type{}, std::true_type{});
2064 template <
typename T>
2065 std::false_type member_type_test(...);
2071 template <
typename T>
2072 struct is_member :
decltype(detail::member_type_test<T>(0))
2079 template <
typename T>
2080 [[maybe_unused]]
static constexpr bool is_member_v{ is_member<T>::value };
2084 template <
typename T>
2085 struct is_field_2 : std::is_base_of<
typename T::member_type, member::field>
2093 template <
typename T>
2094 struct is_field : std::conjunction<is_member<T>, detail::is_field_2<T>>
2101 template <
typename T>
2102 [[maybe_unused]]
static constexpr bool is_field_v{ is_field<T>::value };
2106 template <
typename T>
2107 struct is_function_2 : std::is_base_of<
typename T::member_type, member::function>
2115 template <
typename T>
2116 struct is_function : std::conjunction<is_member<T>, detail::is_function_2<T>>
2123 template <
typename T>
2124 [[maybe_unused]]
static constexpr bool is_function_v{ is_function<T>::value };
2130 template <
typename T>
2131 struct is_type : is_instance_of<descriptor::type_descriptor, T>
2139 template <
typename T>
2140 [[maybe_unused]]
constexpr bool is_type_v{ is_type<T>::value };
2145 template <
typename T>
2146 struct is_descriptor : std::disjunction<is_type<T>, is_member<T>>
2153 template <
typename T>
2154 [[maybe_unused]]
static constexpr bool is_descriptor_v{ is_descriptor<T>::value };
2158 template <
typename T>
2159 struct is_property : std::bool_constant<
2160 trait::is_function_v<T> && trait::contains_v<attr::property,
typename T::attribute_types>>
2165 template <
typename T>
2166 [[maybe_unused]]
static constexpr bool is_property_v{ is_property<T>::value };
2173 namespace descriptor
2177 template <
typename Member>
2178 struct static_field_invoker
2180 static constexpr auto invoke() ->
decltype(*Member::pointer)
2182 return *Member::pointer;
2185 template <
typename U,
typename M = Member, std::enable_if_t<M::is_writable,
int> = 0>
2186 static constexpr auto invoke(U&& value) ->
decltype(*Member::pointer = std::forward<U>(value))
2188 return *Member::pointer = std::forward<U>(value);
2192 template <
typename Member>
2193 struct instance_field_invoker
2195 template <
typename T>
2196 static constexpr auto invoke(T&& target) ->
decltype(target.*(Member::pointer))
2198 return target.*(Member::pointer);
2201 template <
typename T,
typename U,
typename M = Member, std::enable_if_t<M::is_writable,
int> = 0>
2202 static constexpr auto invoke(T&& target, U&& value) ->
decltype(target.*(Member::pointer) = std::forward<U>(value))
2204 return target.*(Member::pointer) = std::forward<U>(value);
2208 template <
typename Member>
2209 static_field_invoker<Member> field_type_switch(std::true_type);
2211 template <
typename Member>
2212 instance_field_invoker<Member> field_type_switch(std::false_type);
2214 template <
typename Member>
2215 constexpr decltype(
nullptr) get_function_pointer(...)
2220 template <
typename Member>
2221 constexpr auto get_function_pointer(
int) ->
decltype(Member::pointer())
2223 return Member::pointer();
2226 template <
typename Member,
typename Pointer>
2227 constexpr decltype(
nullptr) resolve_function_pointer(...)
2232 template <
typename Member,
typename Pointer>
2233 constexpr auto resolve_function_pointer(
int) ->
decltype(Member::
template resolve<Pointer>())
2235 return Member::
template resolve<Pointer>();
2238 template <
typename T, size_t N>
2239 using make_descriptor = std::conditional_t<refl::trait::is_field_v<refl::detail::member_info<T, N>>,
2240 field_descriptor<T, N>,
2241 std::conditional_t<refl::trait::is_function_v<refl::detail::member_info<T, N>>,
2242 function_descriptor<T, N>,
2246 template <
typename T>
2247 type_list<> enumerate_members(std::index_sequence<>);
2249 template <
typename T, size_t... Idx>
2250 type_list<make_descriptor<T, Idx>...> enumerate_members(std::index_sequence<Idx...>);
2252 template <
typename T>
2253 struct declared_member_list
2255 static_assert(refl::trait::is_reflectable_v<T>,
"This type does not support reflection!");
2256 using type =
decltype(enumerate_members<T>(std::make_index_sequence<refl::detail::type_info<T>::member_count>{}));
2259 template <
typename T>
2260 using attribute_types = trait::as_type_list_t<std::remove_cv_t<
decltype(refl::detail::type_info<T>::attributes)>>;
2265 template <
typename... TypeLists>
2266 struct flatten<type_list<TypeLists...>> : trait::concat<TypeLists...>
2270 template <
typename T,
typename Base>
2271 static constexpr void validate_base()
2273 static_assert(std::is_base_of_v<Base, T>,
"Base is not a base type of T!");
2276 template <
typename T,
typename... Bases>
2277 static constexpr void validate_bases(type_list<Bases...>)
2279 util::ignore((validate_base<T, Bases>(), 0)...);
2282 template <
typename T>
2283 static constexpr auto get_declared_base_type_list()
2285 if constexpr (trait::contains_instance_v<attr::base_types, attribute_types<T>>) {
2286 using base_types_type = trait::remove_qualifiers_t<
decltype(util::get_instance<attr::base_types>(refl::detail::type_info<T>::attributes))>;
2287 validate_bases<T>(base_types_type::list);
2288 return typename base_types_type::list_type{};
2291 return type_list<>{};
2295 template <
typename T>
2296 struct declared_base_type_list
2298 using type =
decltype(get_declared_base_type_list<T>());
2301 template <
typename T>
2302 struct base_type_list;
2304 template <
typename T>
2305 static constexpr auto get_base_type_list()
2307 if constexpr (trait::contains_instance_v<attr::base_types, attribute_types<T>>) {
2308 using declared_bases =
typename declared_base_type_list<T>::type;
2309 using rec_bases =
typename flatten<trait::map_t<base_type_list, declared_bases>>::type;
2310 return trait::unique_t<trait::concat_t<declared_bases, rec_bases>>{};
2313 return type_list<>{};
2317 template <
typename T>
2318 struct base_type_list
2320 using type =
decltype(get_base_type_list<T>());
2323 template <
typename T>
2324 struct member_list : flatten<trait::map_t<declared_member_list, trait::prepend_t<T,
typename base_type_list<T>::type>>>
2331 template <
typename T>
2332 using declared_member_list =
typename detail::declared_member_list<T>::type;
2335 template <
typename T>
2336 using member_list =
typename detail::member_list<T>::type;
2341 template <
typename T, size_t N>
2342 class member_descriptor_base
2346 typedef refl::detail::member_info<T, N> member;
2360 typedef T declaring_type;
2363 typedef typename member::member_type member_type;
2369 typedef trait::as_type_list_t<std::remove_cv_t<
decltype(member::attributes)>> attribute_types;
2375 static constexpr type_descriptor<T> declarator{ };
2381 static constexpr auto name{ member::name };
2387 static constexpr auto attributes{ member::attributes };
2394 template <
typename T, size_t N>
2395 class field_descriptor :
public member_descriptor_base<T, N>
2397 using typename member_descriptor_base<T, N>::member;
2398 static_assert(trait::is_field_v<member>);
2412 typedef typename member::value_type value_type;
2418 static constexpr bool is_static{ !std::is_member_object_pointer_v<
decltype(member::pointer)> };
2424 static constexpr bool is_writable{ !std::is_const_v<value_type> };
2430 static constexpr auto pointer{ member::pointer };
2434 using invoker =
decltype(detail::field_type_switch<field_descriptor>(std::bool_constant<is_static>{}));
2442 template <
decltype(
nullptr) =
nullptr>
2443 static constexpr decltype(
auto) get()
noexcept
2445 return *member::pointer;
2452 template <
typename U>
2453 static constexpr decltype(
auto) get(U&& target)
noexcept
2455 return target.*(member::pointer);
2462 template <
typename... Args>
2463 constexpr auto operator()(Args&&... args)
const noexcept ->
decltype(invoker::invoke(std::forward<Args>(args)...))
2465 return invoker::invoke(std::forward<Args>(args)...);
2473 template <
typename T, size_t N>
2474 class function_descriptor :
public member_descriptor_base<T, N>
2476 using typename member_descriptor_base<T, N>::member;
2477 static_assert(trait::is_function_v<member>);
2487 template <
typename... Args>
2488 static constexpr auto invoke(Args&&... args) ->
decltype(member::invoke(std::declval<Args>()...))
2490 return member::invoke(std::forward<Args>(args)...);
2497 template <
typename... Args>
2498 using return_type =
decltype(member::invoke(std::declval<Args>()...));
2504 template <
typename... Args>
2505 constexpr auto operator()(Args&&... args)
const ->
decltype(invoke(std::declval<Args>()...))
2507 return invoke(std::forward<Args>(args)...);
2514 static constexpr auto pointer{ detail::get_function_pointer<member>(0) };
2521 static constexpr bool is_resolved{ !std::is_same_v<
decltype(pointer),
const decltype(
nullptr)> };
2527 template <
typename Pointer>
2528 static constexpr bool can_resolve()
2530 return !std::is_same_v<
decltype(resolve<Pointer>()),
decltype(
nullptr)>;
2539 template <
typename Pointer>
2540 static constexpr auto resolve()
2542 return detail::resolve_function_pointer<member, Pointer>(0);
2548 template <
typename T>
2549 class type_descriptor
2553 static_assert(refl::trait::is_reflectable_v<T>,
"This type does not support reflection!");
2555 typedef refl::detail::type_info<T> type_info;
2575 typedef typename detail::declared_base_type_list<T>::type declared_base_types;
2581 typedef typename detail::base_type_list<T>::type base_types;
2587 typedef declared_member_list<T> declared_member_types;
2593 typedef member_list<T> member_types;
2599 typedef detail::attribute_types<T> attribute_types;
2605 static constexpr declared_base_types declared_bases{};
2611 static constexpr base_types bases{};
2617 static constexpr declared_member_types declared_members{ };
2623 static constexpr member_types members{ };
2629 static constexpr const auto name{ type_info::name };
2635 static constexpr const auto attributes{ type_info::attributes };
2654 template <
typename Descriptor>
2655 constexpr auto get_name(Descriptor d)
noexcept
2657 static_assert(trait::is_descriptor_v<Descriptor>);
2671 template <
typename Descriptor>
2672 constexpr const auto& get_attributes(Descriptor d)
noexcept
2674 static_assert(trait::is_descriptor_v<Descriptor>);
2675 return d.attributes;
2688 template <
typename Descriptor>
2689 constexpr auto get_attribute_types(Descriptor d)
noexcept
2691 static_assert(trait::is_descriptor_v<Descriptor>);
2692 return trait::as_type_list_t<std::remove_cv_t<
decltype(d.attributes)>>{};
2711 template <
typename TypeDescriptor>
2712 constexpr auto get_declared_base_types(TypeDescriptor t)
noexcept
2714 static_assert(trait::is_type_v<TypeDescriptor>);
2715 return t.declared_bases;
2734 template <
typename TypeDescriptor>
2735 constexpr auto get_base_types(TypeDescriptor t)
noexcept
2737 static_assert(trait::is_type_v<TypeDescriptor>);
2755 template <
typename TypeDescriptor>
2756 constexpr auto get_declared_members(TypeDescriptor t)
noexcept
2758 static_assert(trait::is_type_v<TypeDescriptor>);
2759 return t.declared_members;
2776 template <
typename TypeDescriptor>
2777 constexpr auto get_members(TypeDescriptor t)
noexcept
2779 static_assert(trait::is_type_v<TypeDescriptor>);
2794 template <
typename MemberDescriptor>
2795 constexpr auto get_declarator(MemberDescriptor d)
noexcept
2797 static_assert(trait::is_member_v<MemberDescriptor>);
2798 return d.declarator;
2819 template <
typename MemberDescriptor>
2820 constexpr auto get_pointer(MemberDescriptor d)
noexcept
2822 static_assert(trait::is_member_v<MemberDescriptor>);
2843 template <
typename MemberDescriptor,
typename... Args>
2844 constexpr auto invoke(MemberDescriptor d, Args&&... args)
noexcept ->
decltype(d(std::forward<Args>(args)...))
2846 return d(std::forward<Args>(args)...);
2862 template <
typename FieldDescriptor>
2863 constexpr auto is_static(FieldDescriptor d)
noexcept
2865 static_assert(trait::is_field_v<FieldDescriptor>);
2882 template <
typename FieldDescriptor>
2883 constexpr auto is_const(FieldDescriptor d)
noexcept
2885 static_assert(trait::is_field_v<FieldDescriptor>);
2893 template <
typename FunctionDescriptor,
typename... Args>
2894 using result_type =
typename FunctionDescriptor::
template result_type<Args...>;
2910 template <
typename FunctionDescriptor>
2911 constexpr auto is_resolved(FunctionDescriptor d)
noexcept
2913 static_assert(trait::is_function_v<FunctionDescriptor>);
2914 return d.is_resolved;
2932 template <
typename Pointer,
typename FunctionDescriptor>
2933 constexpr auto can_resolve(FunctionDescriptor d)
noexcept
2935 static_assert(trait::is_function_v<FunctionDescriptor>);
2936 return d.
template can_resolve<Pointer>();
2953 template <
typename Pointer,
typename FunctionDescriptor>
2954 constexpr auto resolve(FunctionDescriptor d)
noexcept
2956 static_assert(trait::is_function_v<FunctionDescriptor>);
2957 return d.
template resolve<Pointer>();
2971 template <
typename Descriptor>
2972 constexpr bool is_field(Descriptor)
noexcept
2974 static_assert(trait::is_descriptor_v<Descriptor>);
2975 return trait::is_field_v<Descriptor>;
2989 template <
typename Descriptor>
2990 constexpr bool is_function(Descriptor)
noexcept
2992 static_assert(trait::is_descriptor_v<Descriptor>);
2993 return trait::is_function_v<Descriptor>;
3006 template <
typename Descriptor>
3007 constexpr bool is_type(Descriptor)
noexcept
3009 static_assert(trait::is_descriptor_v<Descriptor>);
3010 return trait::is_type_v<Descriptor>;
3021 template <
typename A,
typename Descriptor>
3022 constexpr bool has_attribute(Descriptor)
noexcept
3024 static_assert(trait::is_descriptor_v<Descriptor>);
3025 return trait::contains_base_v<A,
typename Descriptor::attribute_types>;
3036 template <
template<
typename...>
typename A,
typename Descriptor>
3037 constexpr bool has_attribute(Descriptor)
noexcept
3039 static_assert(trait::is_descriptor_v<Descriptor>);
3040 return trait::contains_instance_v<A,
typename Descriptor::attribute_types>;
3051 template <
typename A,
typename Descriptor>
3052 constexpr const A& get_attribute(Descriptor d)
noexcept
3054 static_assert(trait::is_descriptor_v<Descriptor>);
3055 return util::get<A>(d.attributes);
3066 template <
template<
typename...>
typename A,
typename Descriptor>
3067 constexpr const auto& get_attribute(Descriptor d)
noexcept
3069 static_assert(trait::is_descriptor_v<Descriptor>);
3070 return util::get_instance<A>(d.attributes);
3084 template <
typename MemberDescriptor>
3085 constexpr bool is_property(MemberDescriptor d)
noexcept
3087 static_assert(trait::is_member_v<MemberDescriptor>);
3088 return has_attribute<attr::property>(d);
3102 template <
typename FunctionDescriptor>
3103 constexpr attr::property get_property(FunctionDescriptor d)
noexcept
3105 static_assert(trait::is_function_v<FunctionDescriptor>);
3106 return get_attribute<attr::property>(d);
3113 template <
typename T>
3127 template <
typename MemberDescriptor>
3128 constexpr bool is_readable(MemberDescriptor)
noexcept
3130 static_assert(trait::is_member_v<MemberDescriptor>);
3131 if constexpr (trait::is_property_v<MemberDescriptor>) {
3132 if constexpr (std::is_invocable_v<MemberDescriptor,
const typename MemberDescriptor::declaring_type&>) {
3133 using return_type =
typename MemberDescriptor::
template return_type<
const typename MemberDescriptor::declaring_type&>;
3134 return !std::is_void_v<return_type>;
3141 return trait::is_field_v<MemberDescriptor>;
3155 template <
typename MemberDescriptor>
3156 constexpr bool is_writable(MemberDescriptor)
noexcept
3158 static_assert(trait::is_member_v<MemberDescriptor>);
3159 if constexpr (trait::is_property_v<MemberDescriptor>) {
3160 return std::is_invocable_v<MemberDescriptor,
typename MemberDescriptor::declaring_type&, detail::placeholder>;
3162 else if constexpr (trait::is_field_v<MemberDescriptor>) {
3163 return !std::is_const_v<
typename trait::remove_qualifiers_t<MemberDescriptor>::value_type>;
3172 template <
typename T>
3173 struct get_type_descriptor
3175 typedef type_descriptor<T> type;
3191 template <
typename TypeDescriptor>
3192 [[deprecated]]
constexpr auto has_bases(TypeDescriptor t)
noexcept
3194 static_assert(trait::is_type_v<TypeDescriptor>);
3195 return has_attribute<attr::base_types>(t);
3211 template <
typename TypeDescriptor>
3212 [[deprecated]]
constexpr auto get_bases(TypeDescriptor t)
noexcept
3214 static_assert(trait::is_type_v<TypeDescriptor>);
3215 static_assert(has_bases(t),
"Target type does not have a bases<A, B, ...> attribute.");
3217 constexpr auto bases = get_attribute<attr::base_types>(t);
3218 using base_types =
typename decltype(bases)::list_type;
3219 return trait::map_t<detail::get_type_descriptor, base_types>{};
3229 template <
typename TypeDescriptor>
3230 constexpr auto get_simple_name(TypeDescriptor t)
3232 static_assert(trait::is_type_v<TypeDescriptor>);
3233 constexpr size_t template_start = t.name.find(
'<');
3234 constexpr size_t scope_last = t.name.rfind(
':', template_start);
3235 if constexpr (scope_last == const_string<0>::npos) {
3239 return t.name.
template substr<scope_last + 1, template_start - scope_last - 1>();
3251 template <
typename MemberDescriptor>
3252 constexpr auto get_debug_name_const(MemberDescriptor d)
3254 static_assert(trait::is_member_v<MemberDescriptor>);
3255 return d.declarator.name +
"::" + d.name;
3265 template <
typename MemberDescriptor>
3266 const char* get_debug_name(MemberDescriptor d)
3268 static_assert(trait::is_member_v<MemberDescriptor>);
3269 static const std::string name(get_debug_name_const(d).str());
3270 return name.c_str();
3275 constexpr bool is_upper(
char ch)
3277 return ch >=
'A' && ch <=
'Z';
3280 constexpr char to_upper(
char ch)
3282 return ch >=
'a' && ch <=
'z'
3283 ?
char(ch + (
'A' -
'a'))
3287 constexpr char to_lower(
char ch)
3289 return ch >=
'A' && ch <=
'Z'
3290 ?
char(ch + (
'a' -
'A'))
3294 template <
typename T,
bool PreferUpper>
3295 constexpr auto normalize_bare_accessor_name()
3297 constexpr auto str = T::name.
template substr<3>();
3298 if constexpr (str.data[0] ==
'_') {
3299 return str.
template substr<1>();
3301 else if constexpr (!PreferUpper && str.data[0] >=
'A' && str.data[0] <=
'Z') {
3302 return make_const_string(to_lower(str.data[0])) + str.
template substr<1>();
3304 else if constexpr (PreferUpper) {
3305 return make_const_string(to_upper(str.data[0])) + str.
template substr<1>();
3312 template <
typename T>
3313 constexpr auto normalize_accessor_name(
const T)
3316 if constexpr (t.name.size > 3) {
3317 constexpr auto prefix = t.name.
template substr<0, 3>();
3318 constexpr bool cont_snake_or_camel = (t.name.size > 4 && t.name.data[3] ==
'_' && !is_upper(t.name.data[4])) || is_upper(t.name.data[3]);
3319 constexpr bool cont_pascal = is_upper(t.name.data[3]);
3321 if constexpr ((is_readable(T{}) && ((prefix ==
"Get" && cont_pascal) || (prefix ==
"get" && cont_snake_or_camel)))
3322 || (is_writable(T{}) && ((prefix ==
"Set" && cont_pascal) || (prefix ==
"set" && cont_snake_or_camel)))) {
3323 constexpr bool prefer_upper = is_upper(prefix.data[0]);
3324 return normalize_bare_accessor_name<T, prefer_upper>();
3335 template <
typename T>
3336 constexpr auto get_display_name(
const T t)
noexcept
3338 if constexpr (trait::is_property_v<T>) {
3339 if constexpr (util::get<attr::property>(t.attributes).friendly_name) {
3343 return detail::normalize_accessor_name(t);
3351 template <
template <
typename, size_t>
typename MemberDescriptor,
typename T, size_t N>
3352 constexpr size_t get_member_index(MemberDescriptor<T, N>)
noexcept
3362 static constexpr auto is_readable_p = [](
auto m) {
return is_readable(m); };
3363 static constexpr auto is_writable_p = [](
auto m) {
return is_writable(m); };
3365 template <
typename Member>
3366 static constexpr auto display_name_equals_p = [](
auto m) {
3367 return get_display_name_const(m) == get_display_name_const(Member{});
3370 template <
typename WritableMember>
3371 static constexpr bool has_reader_search(WritableMember)
3373 #ifdef REFL_DISALLOW_SEARCH_FOR_RW
3374 static_assert(WritableMember::name.data[0] == 0,
3375 "REFL_DISALLOW_SEARCH_FOR_RW is defined. Make sure your property getters and setter are defined one after the other!");
3377 using member_types =
typename type_descriptor<
typename WritableMember::declaring_type>::declared_member_types;
3379 using property_types =
typename trait::filter_t<trait::is_property, member_types>;
3380 constexpr auto readable_properties = filter(property_types{}, detail::is_readable_p);
3381 return contains(readable_properties, display_name_equals_p<WritableMember>);
3384 template <
typename ReadableMember>
3385 static constexpr bool has_writer_search(ReadableMember)
3387 #ifdef REFL_DISALLOW_SEARCH_FOR_RW
3388 static_assert(ReadableMember::name.data[0] == 0,
3389 "REFL_DISALLOW_SEARCH_FOR_RW is defined. Make sure your property getters and setter are defined one after the other!");
3391 using member_types =
typename type_descriptor<
typename ReadableMember::declaring_type>::declared_member_types;
3393 using property_types =
typename trait::filter_t<trait::is_property, member_types>;
3394 constexpr auto writable_properties = filter(property_types{}, detail::is_writable_p);
3395 return contains(writable_properties, display_name_equals_p<ReadableMember>);
3398 template <
typename WritableMember>
3399 static constexpr auto get_reader_search(WritableMember)
3401 #ifdef REFL_DISALLOW_SEARCH_FOR_RW
3402 static_assert(WritableMember::name.data[0] == 0,
3403 "REFL_DISALLOW_SEARCH_FOR_RW is defined. Make sure your property getters and setter are defined one after the other!");
3405 using member_types =
typename type_descriptor<
typename WritableMember::declaring_type>::declared_member_types;
3407 using property_types =
typename trait::filter_t<trait::is_property, member_types>;
3408 constexpr auto readable_properties = filter(property_types{}, detail::is_readable_p);
3409 return find_one(readable_properties, display_name_equals_p<WritableMember>);
3412 template <
typename ReadableMember>
3413 static constexpr auto get_writer_search(ReadableMember)
3415 #ifdef REFL_DISALLOW_SEARCH_FOR_RW
3416 static_assert(ReadableMember::name.data[0] == 0,
3417 "REFL_DISALLOW_SEARCH_FOR_RW is defined. Make sure your property getters and setter are defined one after the other!");
3419 using member_types =
typename type_descriptor<
typename ReadableMember::declaring_type>::declared_member_types;
3421 using property_types =
typename trait::filter_t<trait::is_property, member_types>;
3422 constexpr auto writable_properties = filter(property_types{}, detail::is_writable_p);
3423 return find_one(writable_properties, display_name_equals_p<ReadableMember>);
3452 template <
typename Descriptor>
3453 const char* get_display_name(Descriptor d)
noexcept
3455 static_assert(trait::is_descriptor_v<Descriptor>);
3456 static const std::string name(detail::get_display_name(d));
3457 return name.c_str();
3465 template <
typename Descriptor>
3466 constexpr auto get_display_name_const(Descriptor d)
noexcept
3468 static_assert(trait::is_descriptor_v<Descriptor>);
3469 return detail::get_display_name(d);
3478 template <
typename ReadableMember>
3479 constexpr bool has_writer(ReadableMember member)
3481 static_assert(is_writable(member) || is_property(member));
3482 if constexpr (is_writable(member)) {
3486 [[maybe_unused]]
constexpr auto match = [](
auto m) {
3487 return is_property(m) && is_writable(m) && get_display_name_const(m) == get_display_name_const(ReadableMember{});
3490 using member_types =
typename type_descriptor<
typename ReadableMember::declaring_type>::declared_member_types;
3491 constexpr auto member_index = detail::get_member_index(member);
3494 if constexpr (member_index != 0) {
3495 using likely_match = trait::get_t<member_index - 1, member_types>;
3496 if constexpr (match(likely_match{})) {
3502 if constexpr (member_index != member_types::size - 1) {
3503 using likely_match = trait::get_t<member_index + 1, member_types>;
3504 if constexpr (match(likely_match{})) {
3508 return detail::has_writer_search(member);
3512 return detail::has_writer_search(member);
3523 template <
typename WritableMember>
3524 constexpr bool has_reader(WritableMember member)
3526 static_assert(is_readable(member) || is_property(member));
3527 if constexpr (is_readable(member)) {
3531 [[maybe_unused]]
constexpr auto match = [](
auto m) {
3532 return is_property(m) && is_readable(m) && get_display_name_const(m) == get_display_name_const(WritableMember{});
3535 using member_types =
typename type_descriptor<
typename WritableMember::declaring_type>::declared_member_types;
3536 constexpr auto member_index = detail::get_member_index(member);
3539 if constexpr (member_index != member_types::size - 1) {
3540 using likely_match = trait::get_t<member_index + 1, member_types>;
3541 if constexpr (match(likely_match{})) {
3547 if constexpr (member_index != 0) {
3548 using likely_match = trait::get_t<member_index - 1, member_types>;
3549 if constexpr (match(likely_match{})) {
3553 return detail::has_reader_search(member);
3557 return detail::has_reader_search(member);
3568 template <
typename ReadableMember>
3569 constexpr auto get_writer(ReadableMember member)
3571 static_assert(is_writable(member) || is_property(member));
3572 if constexpr (is_writable(member)) {
3575 else if constexpr (has_writer(member)) {
3576 constexpr auto match = [](
auto m) {
3577 return is_property(m) && is_writable(m) && get_display_name_const(m) == get_display_name_const(ReadableMember{});
3580 using member_types =
typename type_descriptor<
typename ReadableMember::declaring_type>::declared_member_types;
3581 constexpr auto member_index = detail::get_member_index(member);
3584 if constexpr (member_index != 0) {
3585 using likely_match = trait::get_t<member_index - 1, member_types>;
3586 if constexpr (match(likely_match{})) {
3587 return likely_match{};
3592 if constexpr (member_index != member_types::size - 1) {
3593 using likely_match = trait::get_t<member_index + 1, member_types>;
3594 if constexpr (match(likely_match{})) {
3595 return likely_match{};
3598 return detail::get_writer_search(member);
3602 return detail::get_writer_search(member);
3606 static_assert(has_writer(member),
"The property is not writable (could not find a setter method)!");
3616 template <
typename WritableMember>
3617 constexpr auto get_reader(WritableMember member)
3619 static_assert(is_readable(member) || is_property(member));
3620 if constexpr (is_readable(member)) {
3623 else if constexpr (has_reader(member)) {
3624 constexpr auto match = [](
auto m) {
3625 return is_property(m) && is_readable(m) && get_display_name_const(m) == get_display_name_const(WritableMember{});
3628 using member_types =
typename type_descriptor<
typename WritableMember::declaring_type>::declared_member_types;
3629 constexpr auto member_index = detail::get_member_index(member);
3632 if constexpr (member_index != member_types::size - 1) {
3633 using likely_match = trait::get_t<member_index + 1, member_types>;
3634 if constexpr (match(likely_match{})) {
3635 return likely_match{};
3640 if constexpr (member_index != 0) {
3641 using likely_match = trait::get_t<member_index - 1, member_types>;
3642 if constexpr (match(likely_match{})) {
3643 return likely_match{};
3646 return detail::get_reader_search(member);
3650 return detail::get_reader_search(member);
3654 static_assert(has_reader(member),
"The property is not readable (could not find a getter method)!");
3660 using descriptor::member_list;
3661 using descriptor::declared_member_list;
3662 using descriptor::field_descriptor;
3663 using descriptor::function_descriptor;
3664 using descriptor::type_descriptor;
3667 template <
typename T>
3668 constexpr bool is_reflectable()
noexcept
3670 return trait::is_reflectable_v<T>;
3674 template <
typename T>
3675 constexpr bool is_reflectable(
const T&)
noexcept
3677 return trait::is_reflectable_v<T>;
3681 template<
typename T>
3682 constexpr type_descriptor<T> reflect()
noexcept
3688 template<
typename T>
3689 constexpr type_descriptor<T> reflect(
const T&)
noexcept
3694 #ifndef REFL_DETAIL_FORCE_EBO
3696 #define REFL_DETAIL_FORCE_EBO __declspec(empty_bases)
3698 #define REFL_DETAIL_FORCE_EBO
3707 template <
typename Derived,
typename Target>
3712 template <
typename T>
3713 struct get_member_info;
3715 template <
typename T, size_t N>
3716 struct get_member_info<refl::function_descriptor<T, N>>
3718 using type = refl::detail::member_info<T, N>;
3721 template <
typename T, size_t N>
3722 struct get_member_info<refl::field_descriptor<T, N>>
3724 using type = refl::detail::member_info<T, N>;
3727 template <
typename T,
typename U>
3728 constexpr T& static_ref_cast(U& value)
noexcept
3730 return static_cast<T&>(value);
3733 template <
typename T,
typename U>
3734 constexpr const T& static_ref_cast(
const U& value)
noexcept
3736 return static_cast<
const T&>(value);
3739 template <
typename... Results>
3740 constexpr type_list<Results...> get_members_skip_shadowed(type_list<>, type_list<Results...>)
3745 template <
typename Member,
typename... Members,
typename... Results>
3746 constexpr auto get_members_skip_shadowed(type_list<Member, Members...>, type_list<Results...>)
3748 if constexpr ((... || (Results::name == Member::name))) {
3749 return get_members_skip_shadowed(type_list<Members...>{}, type_list<Results...>{});
3752 return get_members_skip_shadowed(type_list<Members...>{}, type_list<Results..., Member>{});
3756 template <
typename T>
3757 using members_skip_shadowed =
decltype(get_members_skip_shadowed(member_list<T>{}, type_list<>{}));
3760 template <
typename Derived,
typename Func>
3761 struct REFL_DETAIL_FORCE_EBO function_proxy :
public get_member_info<Func>::type::
template remap<function_proxy<Derived, Func>>
3767 template <
typename Self,
typename... Args>
3768 static constexpr decltype(
auto) invoke_impl(Self&& self, Args&& ... args)
3770 return Derived::
template invoke_impl<Func>(static_ref_cast<Derived>(self), std::forward<Args>(args)...);
3774 template <
typename,
typename>
3778 template <
typename Derived,
typename... Members>
3779 struct REFL_DETAIL_FORCE_EBO function_proxies<Derived, type_list<Members...>> :
public function_proxy<Derived, Members>...
3784 template <
typename Derived,
typename Field>
3785 struct REFL_DETAIL_FORCE_EBO field_proxy :
public get_member_info<Field>::type::
template remap<field_proxy<Derived, Field>>
3791 template <
typename Self,
typename... Args>
3792 static constexpr decltype(
auto) invoke_impl(Self&& self, Args&& ... args)
3794 return Derived::
template invoke_impl<Field>(static_ref_cast<Derived>(self), std::forward<Args>(args)...);
3799 template <
typename,
typename>
3803 template <
typename Derived,
typename... Members>
3804 struct REFL_DETAIL_FORCE_EBO field_proxies<Derived, type_list<Members...>> :
public field_proxy<Derived, Members>...
3808 template <
typename T>
3809 using functions = trait::filter_t<trait::is_function, members_skip_shadowed<T>>;
3811 template <
typename T>
3812 using fields = trait::filter_t<trait::is_field, members_skip_shadowed<T>>;
3834 template <
typename Derived,
typename Target>
3836 :
public detail::function_proxies<proxy<Derived, Target>, detail::functions<Target>>
3837 ,
public detail::field_proxies<proxy<Derived, Target>, detail::fields<Target>>
3840 sizeof(detail::function_proxies<proxy<Derived, Target>, detail::functions<Target>>) == 1 &&
3841 sizeof(detail::field_proxies<proxy<Derived, Target>, detail::fields<Target>>) == 1,
3842 "Multiple inheritance EBO did not kick in! "
3843 "You could try defining the REFL_DETAIL_FORCE_EBO macro appropriately to enable it on the required types. "
3844 "Default for MSC is `__declspec(empty_bases)`.");
3847 trait::is_reflectable_v<Target>,
3848 "Target type must be reflectable!");
3850 typedef Target target_type;
3852 constexpr proxy()
noexcept {}
3856 template <
typename P,
typename F>
3857 friend struct detail::function_proxy;
3859 template <
typename P,
typename F>
3860 friend struct detail::field_proxy;
3863 template <
typename Member,
typename Self,
typename... Args>
3864 static constexpr decltype(
auto) invoke_impl(Self&& self, Args&& ... args)
3866 return Derived::
template invoke_impl<Member>(detail::static_ref_cast<Derived>(self), std::forward<Args>(args)...);
3878 template <
typename T>
3882 template <
typename Derived,
typename Target>
3883 static std::true_type test(runtime::proxy<Derived, Target>*);
3884 static std::false_type test(...);
3886 static constexpr bool value{ !std::is_reference_v<T> &&
decltype(test(std::declval<remove_qualifiers_t<T>*>()))::value };
3889 template <
typename T>
3890 [[maybe_unused]]
static constexpr bool is_proxy_v{ is_proxy<T>::value };
3895 template <
typename CharT,
typename T>
3896 void debug(std::basic_ostream<CharT>& os,
const T& value,
bool compact =
false);
3900 template <
typename CharT,
typename T,
typename =
decltype(std::declval<std::basic_ostream<CharT>&>() << std::declval<T>())>
3901 std::true_type is_ostream_printable_test(
int);
3903 template <
typename CharT,
typename T>
3904 std::false_type is_ostream_printable_test(...);
3906 template <
typename CharT,
typename T>
3907 constexpr bool is_ostream_printable_v{
decltype(is_ostream_printable_test<CharT, T>(0))::value };
3911 [[maybe_unused]]
int next_depth(
int depth)
3913 return depth == -1 || depth > 8
3919 template <
typename CharT>
3920 void indent(std::basic_ostream<CharT>& os,
int depth)
3922 for (
int i = 0; i < depth; i++) {
3927 template <
typename CharT,
typename T>
3928 void debug_impl(std::basic_ostream<CharT>& os,
const T& value, [[maybe_unused]]
int depth);
3930 template <
typename CharT,
typename T>
3931 void debug_detailed(std::basic_ostream<CharT>& os,
const T& value,
int depth)
3933 using type_descriptor = type_descriptor<T>;
3934 bool compact = depth == -1;
3936 os << type_descriptor::name <<
" { ";
3937 if (!compact) os <<
'\n';
3939 constexpr auto readable_members = filter(type_descriptor::members, [](
auto member) {
return is_readable(member); });
3940 for_each(readable_members, [&](
auto member, [[maybe_unused]]
auto index) {
3941 int new_depth = next_depth(depth);
3943 indent(os, new_depth);
3944 os << get_display_name(member) <<
" = ";
3946 if constexpr (util::contains_instance<attr::debug>(member.attributes)) {
3948 auto debug_attr = util::get_instance<attr::debug>(member.attributes);
3949 debug_attr.write(os, value);
3952 debug_impl(os, member(value), new_depth);
3955 if (!compact || index + 1 != readable_members.size) {
3964 if (compact) os <<
' ';
3969 template <
typename CharT,
typename T>
3970 void debug_reflectable(std::basic_ostream<CharT>& os,
const T& value, [[maybe_unused]]
int depth)
3972 using type_descriptor = type_descriptor<T>;
3973 if constexpr (trait::contains_instance_v<attr::debug,
typename type_descriptor::attribute_types>) {
3975 auto debug_attr = util::get_instance<attr::debug>(type_descriptor::attributes);
3976 debug_attr.write(os, value);
3978 else if constexpr (detail::is_ostream_printable_v<CharT, T>) {
3983 debug_detailed(os, value, depth);
3987 template <
typename CharT,
typename T>
3988 void debug_container(std::basic_ostream<CharT>& os,
const T& value,
int depth)
3990 bool compact = depth == -1;
3993 auto end = value.end();
3994 for (
auto it = value.begin(); it != end; ++it)
3996 if (!compact) os <<
'\n';
3997 int new_depth = next_depth(depth);
3998 indent(os, new_depth);
4000 debug_impl(os, *it, new_depth);
4001 if (std::next(it, 1) != end) {
4004 else if (!compact) {
4013 template <
typename CharT,
typename T>
4014 void debug_impl(std::basic_ostream<CharT>& os,
const T& value, [[maybe_unused]]
int depth)
4016 using no_pointer_t = std::remove_pointer_t<T>;
4018 if constexpr (std::is_same_v<
bool, T>) {
4019 os << (value ?
"true" :
"false");
4021 else if constexpr (std::is_pointer_v<T> && !std::is_void_v<no_pointer_t> && trait::is_reflectable_v<no_pointer_t>) {
4022 if (value ==
nullptr) {
4027 debug_impl(os, *value, -1);
4030 else if constexpr (trait::is_reflectable_v<T>) {
4031 debug_reflectable(os, value, depth);
4033 else if constexpr (detail::is_ostream_printable_v<CharT, T>) {
4036 else if constexpr (trait::is_container_v<T>) {
4037 debug_container(os, value, depth);
4040 os <<
"(not printable)";
4052 template <
typename CharT,
typename T>
4053 void debug(std::basic_ostream<CharT>& os,
const T& value, [[maybe_unused]]
bool compact)
4055 static_assert(trait::is_reflectable_v<T> || trait::is_container_v<T> || detail::is_ostream_printable_v<CharT, T>,
4056 "Type is not reflectable, not a container of reflectable types and does not support operator<<(std::ostream&, T)!");
4058 detail::debug_impl(os, value, compact ? -1 : 0);
4064 template <
typename CharT,
typename... Ts>
4065 void debug_all(std::basic_ostream<CharT>& os,
const Ts&... values)
4067 refl::runtime::debug(os, std::forward_as_tuple(
static_cast<
const Ts&>(values)...),
true);
4075 template <
typename CharT =
char,
typename T>
4076 std::basic_string<CharT> debug_str(
const T& value,
bool compact =
false)
4078 std::basic_stringstream<CharT> ss;
4079 debug(ss, value, compact);
4086 template <
typename CharT =
char,
typename... Ts>
4087 std::basic_string<CharT> debug_all_str(
const Ts&... values)
4089 return refl::runtime::debug_str(std::forward_as_tuple(
static_cast<
const Ts&>(values)...),
true);
4100 template <
typename U,
typename T,
typename... Args>
4101 U invoke(T&& target,
const char* name, Args&&... args)
4103 using type = std::remove_reference_t<T>;
4104 static_assert(refl::trait::is_reflectable_v<type>,
"Unsupported type!");
4105 typedef type_descriptor<type> type_descriptor;
4107 std::conditional_t<std::is_void_v<U>,
bool, std::optional<U>> result{};
4109 for_each(type_descriptor::members, [&](
auto member) {
4110 using member_t =
decltype(member);
4113 if constexpr (std::is_invocable_r_v<U,
decltype(member), T, Args...>) {
4114 if constexpr (trait::is_member_v<member_t>) {
4115 if (std::strcmp(member.name.c_str(), name) == 0) {
4116 if constexpr (std::is_void_v<U>) {
4117 member(target, std::forward<Args>(args)...);
4121 result.emplace(member(target, std::forward<Args>(args)...));
4129 throw std::runtime_error(std::string(
"The member ")
4130 + type_descriptor::name.str() +
"::" + name
4131 +
" is not compatible with the provided parameters or return type, is not reflected or does not exist!");
4133 if constexpr (!std::is_void_v<U>) {
4134 return std::move(*result);
4142 namespace refl::detail
4144 constexpr bool validate_attr_unique(type_list<>)
noexcept
4150 template <
typename T,
typename... Ts>
4151 constexpr bool validate_attr_unique(type_list<T, Ts...>)
noexcept
4153 constexpr bool cond = (... && (!std::is_same_v<T, Ts> && validate_attr_unique(type_list<Ts>{})));
4154 static_assert(cond,
"Some of the attributes provided have duplicate types!");
4158 template <
typename Req,
typename Attr>
4159 constexpr bool validate_attr_usage()
noexcept
4161 return std::is_base_of_v<Req, Attr>;
4169 template <
typename Req,
typename... Args>
4170 constexpr auto make_attributes(Args&&... args)
noexcept
4172 constexpr bool check_unique = validate_attr_unique(type_list<Args...>{});
4173 static_assert(check_unique,
"Some of the supplied attributes cannot be used on this declaration!");
4175 constexpr bool check_usage = (... && validate_attr_usage<Req, trait::remove_qualifiers_t<Args>>());
4176 static_assert(check_usage,
"Some of the supplied attributes cannot be used on this declaration!");
4178 return std::make_tuple(std::forward<Args>(args)...);
4181 template <
typename T,
typename...>
4191 template <
typename T,
typename... Ts>
4192 using head_t =
typename head<T, Ts...>::type;
4194 template <
typename T,
typename U>
4195 struct transfer_const
4197 using type = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
4200 template <
typename T,
typename U>
4201 struct transfer_volatile
4203 using type = std::conditional_t<std::is_volatile_v<T>, std::add_volatile_t<U>, U>;
4206 template <
typename T,
typename U>
4207 struct transfer_cv : transfer_const<T,
typename transfer_volatile<T, U>::type>
4211 template <
typename T,
typename U>
4212 struct transfer_lvalue_ref
4214 using type = std::conditional_t<std::is_lvalue_reference_v<T>, std::add_lvalue_reference_t<U>, U>;
4217 template <
typename T,
typename U>
4218 struct transfer_rvalue_ref
4220 using type = std::conditional_t<std::is_rvalue_reference_v<T>, std::add_rvalue_reference_t<U>, U>;
4223 template <
typename T,
typename U>
4224 struct transfer_ref : transfer_rvalue_ref<T,
typename transfer_lvalue_ref<T, U>::type>
4228 template <
typename T,
typename U>
4229 struct transfer_cvref : transfer_ref<T,
typename transfer_cv<std::remove_reference_t<T>, U>::type>
4233 template <
typename T,
typename U>
4234 constexpr auto forward_cast(std::remove_reference_t<T>& t) ->
decltype(
static_cast<
typename transfer_cvref<T, U>::type&&>(t))
4236 return static_cast<
typename transfer_cvref<T, U>::type&&>(t);
4239 template <
typename T,
typename U>
4240 constexpr auto forward_cast(std::remove_reference_t<T>&& t) ->
decltype(
static_cast<
typename transfer_cvref<T, U>::type&&>(t))
4242 static_assert(!std::is_lvalue_reference_v<T>,
"template argument substituting T is an lvalue reference type");
4243 return static_cast<
typename transfer_cvref<T, U>::type&&>(t);
4246 template <
typename T>
4247 constexpr auto get_type_name()
4249 if constexpr (trait::is_reflectable_v<T>) {
4250 return type_descriptor<T>::name;
4253 return make_const_string(
"(unknown)");
4263 #define REFL_DETAIL_STR_IMPL(...) #__VA_ARGS__
4267 #define REFL_DETAIL_GROUP(...) __VA_ARGS__
4274 #define REFL_DETAIL_ATTRIBUTES(DeclType, ...)
4275 static constexpr auto attributes{ ::refl::detail::make_attributes<::refl::attr::usage:: DeclType>(__VA_ARGS__) };
4280 #define REFL_DETAIL_TYPE_BODY(TypeName, ...)
4284 static constexpr size_t member_index_offset = __COUNTER__ + 1
;
4285 template <size_t, typename = void>
4299 #define REFL_TYPE(TypeName, ...)
4300 namespace refl_impl::metadata { template<> struct type_info__<TypeName> {
4316 #define REFL_TEMPLATE(TemplateDeclaration, TypeName, ...)
4330 static constexpr size_t member_count{ __COUNTER__ - member_index_offset };
4333 #define REFL_DETAIL_MEMBER_HEADER template<typename Unused__> struct member<__COUNTER__ - member_index_offset, Unused__>
4335 #define REFL_DETAIL_MEMBER_COMMON(MemberType_, MemberName_, ...)
4336 typedef ::refl::member::MemberType_ member_type;
4337 static constexpr auto name{ ::refl::util::make_const_string(REFL_DETAIL_STR(MemberName_)) };
4347 #define REFL_DETAIL_MEMBER_PROXY(MemberName_)
4348 template <typename Proxy> struct remap {
4349 template <typename... Args> decltype(auto) MemberName_(Args&&... args) {
4350 return Proxy::invoke_impl(static_cast<Proxy&>(*this), ::std::forward<Args>(args)...);
4352 template <typename... Args> decltype(auto) MemberName_(Args&&... args) const {
4353 return Proxy::invoke_impl(static_cast<const Proxy&>(*this), ::std::forward<Args>(args)...);
4360 #define REFL_FIELD(FieldName_, ...)
4361 REFL_DETAIL_MEMBER_HEADER
{
4362 REFL_DETAIL_MEMBER_COMMON
(field, FieldName_, __VA_ARGS__)
4364 typedef decltype(type::FieldName_) value_type;
4365 static constexpr auto pointer{ &type::FieldName_ };
4366 REFL_DETAIL_MEMBER_PROXY
(FieldName_);
4372 #define REFL_FUNC(FunctionName_, ...)
4373 REFL_DETAIL_MEMBER_HEADER
{
4374 REFL_DETAIL_MEMBER_COMMON
(function, FunctionName_, __VA_ARGS__)
4376 template<typename Self, typename... Args> static constexpr auto invoke(Self&& self, Args&&... args) -> decltype(::refl::detail::forward_cast<Self, type>(self).FunctionName_(::std::forward<Args>(args)...)) {
4377 return ::refl::detail::forward_cast<Self, type>(self).FunctionName_(::std::forward<Args>(args)...);
4379 template<typename... Args> static constexpr auto invoke(Args&&... args) -> decltype(::refl::detail::head_t<type, Args...>::FunctionName_(::std::declval<Args>()...)) {
4380 return ::refl::detail::head_t<type, Args...>::FunctionName_(::std::forward<Args>(args)...);
4382 template <typename Dummy = void>
4383 static constexpr auto pointer() -> decltype(&::refl::detail::head_t<type, Dummy>::FunctionName_) { return &::refl::detail::head_t<type, Dummy>::FunctionName_; }
4384 template <typename Pointer>
4385 static constexpr auto resolve() -> ::std::decay_t<decltype(Pointer(&type::FunctionName_))> { return Pointer(&type::FunctionName_); }
4386 REFL_DETAIL_MEMBER_PROXY
(FunctionName_);
4393 #define REFL_DETAIL_PRIMITIVE(TypeName)
4398 REFL_DETAIL_PRIMITIVE(
char)
4399 REFL_DETAIL_PRIMITIVE(
wchar_t)
4400 REFL_DETAIL_PRIMITIVE(
char16_t)
4401 REFL_DETAIL_PRIMITIVE(
char32_t)
4402 #ifdef __cpp_lib_char8_t
4403 REFL_DETAIL_PRIMITIVE(char8_t)
4407 REFL_DETAIL_PRIMITIVE(
bool)
4408 REFL_DETAIL_PRIMITIVE(
signed char)
4409 REFL_DETAIL_PRIMITIVE(
unsigned char)
4410 REFL_DETAIL_PRIMITIVE(
signed short)
4411 REFL_DETAIL_PRIMITIVE(
unsigned short)
4412 REFL_DETAIL_PRIMITIVE(
signed int)
4413 REFL_DETAIL_PRIMITIVE(
unsigned int)
4414 REFL_DETAIL_PRIMITIVE(
signed long)
4415 REFL_DETAIL_PRIMITIVE(
unsigned long)
4416 REFL_DETAIL_PRIMITIVE(
signed long long)
4417 REFL_DETAIL_PRIMITIVE(
unsigned long long)
4420 REFL_DETAIL_PRIMITIVE(
float)
4421 REFL_DETAIL_PRIMITIVE(
double)
4422 REFL_DETAIL_PRIMITIVE(
long double)
4425 REFL_DETAIL_PRIMITIVE(
decltype(
nullptr))
4431 #undef REFL_DETAIL_PRIMITIVE
4433 #define REFL_DETAIL_POINTER(Ptr)
4434 template<typename T>
4435 struct type_info__<T Ptr> {
4439 static constexpr auto name{ ::refl::detail::get_type_name<T>() + ::refl::util::make_const_string(#Ptr) };
4440 static constexpr ::std::tuple<> attributes{ };
4441 static constexpr size_t member_count{ 0
};
4448 REFL_DETAIL_POINTER(*);
4449 REFL_DETAIL_POINTER(&);
4450 REFL_DETAIL_POINTER(&&);
4454 #undef REFL_DETAIL_POINTER
4456 namespace refl::detail
4458 template <
typename CharT>
4459 std::basic_string<CharT> convert(
const std::string& str)
4461 return std::basic_string<CharT>(str.begin(), str.end());
4464 #ifdef __cpp_lib_string_view
4465 struct write_basic_string_view
4467 template <
typename CharT,
typename Traits>
4468 void operator()(std::basic_ostream<CharT>& os, std::basic_string_view<CharT, Traits> str)
const
4472 os << std::quoted(str.data());
4475 os << std::quoted(std::basic_string<CharT, Traits>(str.begin(), str.end()));
4481 struct write_basic_string
4483 template <
typename CharT,
typename Traits,
typename Allocator>
4484 void operator()(std::basic_ostream<CharT>& os,
const std::basic_string<CharT, Traits, Allocator>& str)
const
4486 os << std::quoted(str);
4490 struct write_exception
4492 template <
typename CharT>
4493 void operator()(std::basic_ostream<CharT>& os,
const std::exception& e)
const
4495 os << convert<CharT>(
"Exception");
4496 #ifdef REFL_RTTI_ENABLED
4497 os << convert<CharT>(
" (") << convert<CharT>(
typeid(e).name()) << convert<CharT>(
")");
4499 os << convert<CharT>(
": `") << e.what() << convert<CharT>(
"`");
4505 template <
typename CharT,
typename Tuple, size_t... Idx>
4506 void write(std::basic_ostream<CharT>& os, Tuple&& t, std::index_sequence<Idx...>)
const
4509 for_each(type_list<std::integral_constant<size_t, Idx>...>{}, [&](
auto idx_c) {
4510 using idx_t =
decltype(idx_c);
4511 runtime::debug(os, std::get<idx_t::value>(t));
4512 if constexpr (
sizeof...(Idx) - 1 != idx_t::value) {
4513 os << convert<CharT>(
", ");
4519 template <
typename CharT,
typename... Ts>
4520 void operator()(std::basic_ostream<CharT>& os,
const std::tuple<Ts...>& t)
const
4522 write(os, t, std::make_index_sequence<
sizeof...(Ts)>{});
4528 template <
typename CharT,
typename K,
typename V>
4529 void operator()(std::basic_ostream<CharT>& os,
const std::pair<K, V>& t)
const
4532 runtime::debug(os, t.first);
4533 os << convert<CharT>(
", ");
4534 runtime::debug(os, t.second);
4539 struct write_unique_ptr
4541 template <
typename CharT,
typename T,
typename D>
4542 void operator()(std::basic_ostream<CharT>& os,
const std::unique_ptr<T, D>& t)
const
4544 runtime::debug(os, t.get(),
true);
4548 struct write_shared_ptr
4550 template <
typename CharT,
typename T>
4551 void operator()(std::basic_ostream<CharT>& os,
const std::shared_ptr<T>& t)
const
4553 runtime::debug(os, t.get(),
true);
4557 struct write_weak_ptr
4559 template <
typename CharT,
typename T>
4560 void operator()(std::basic_ostream<CharT>& os,
const std::weak_ptr<T>& t)
const
4562 runtime::debug(os, t.lock().get(),
true);
4566 struct write_complex
4568 template <
typename CharT,
typename T>
4569 void operator()(std::basic_ostream<CharT>& os,
const std::complex<T>& t)
const
4571 runtime::debug(os, t.real());
4573 runtime::debug(os, t.imag());
4582 #ifndef REFL_NO_STD_SUPPORT
4584 REFL_TYPE(std::exception, debug{ refl::detail::write_exception() })
4585 REFL_FUNC(what, property{ })
4589 (
typename Elem,
typename Traits,
typename Alloc),
4590 (std::basic_string<Elem, Traits, Alloc>),
4591 debug{ refl::detail::write_basic_string() })
4592 REFL_FUNC(size, property{ })
4593 REFL_FUNC(data, property{ })
4596 #ifdef __cpp_lib_string_view
4599 (
typename Elem,
typename Traits),
4600 (std::basic_string_view<Elem, Traits>),
4601 debug{ refl::detail::write_basic_string_view() })
4602 REFL_FUNC(size, property{ })
4603 REFL_FUNC(data, property{ })
4610 (std::tuple<Ts...>),
4611 debug{ refl::detail::write_tuple() })
4615 (
typename T,
typename D),
4616 (std::unique_ptr<T, D>),
4617 debug{ refl::detail::write_unique_ptr() })
4622 (std::shared_ptr<T>),
4623 debug{ refl::detail::write_shared_ptr() })
4627 (
typename K,
typename V),
4629 debug{ refl::detail::write_pair() })
4632 #ifndef REFL_NO_STD_COMPLEX
4637 debug{ refl::detail::write_complex() })
4644 #ifndef REFL_NO_AUTO_MACRO
4646 #define REFL_DETAIL_EXPAND(x) x
4647 #define REFL_DETAIL_FOR_EACH_0(...)
4648 #define REFL_DETAIL_FOR_EACH_1(what, x, ...) what(x)
4649 #define REFL_DETAIL_FOR_EACH_2(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_1
(what, __VA_ARGS__))
4650 #define REFL_DETAIL_FOR_EACH_3(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_2
(what, __VA_ARGS__))
4651 #define REFL_DETAIL_FOR_EACH_4(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_3
(what, __VA_ARGS__))
4652 #define REFL_DETAIL_FOR_EACH_5(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_4
(what, __VA_ARGS__))
4653 #define REFL_DETAIL_FOR_EACH_6(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_5
(what, __VA_ARGS__))
4654 #define REFL_DETAIL_FOR_EACH_7(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_6
(what, __VA_ARGS__))
4655 #define REFL_DETAIL_FOR_EACH_8(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_7
(what, __VA_ARGS__))
4656 #define REFL_DETAIL_FOR_EACH_9(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_8
(what, __VA_ARGS__))
4657 #define REFL_DETAIL_FOR_EACH_10(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_9
(what, __VA_ARGS__))
4658 #define REFL_DETAIL_FOR_EACH_11(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_10
(what, __VA_ARGS__))
4659 #define REFL_DETAIL_FOR_EACH_12(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_11
(what, __VA_ARGS__))
4660 #define REFL_DETAIL_FOR_EACH_13(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_12
(what, __VA_ARGS__))
4661 #define REFL_DETAIL_FOR_EACH_14(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_13
(what, __VA_ARGS__))
4662 #define REFL_DETAIL_FOR_EACH_15(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_14
(what, __VA_ARGS__))
4663 #define REFL_DETAIL_FOR_EACH_16(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_15
(what, __VA_ARGS__))
4664 #define REFL_DETAIL_FOR_EACH_17(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_16
(what, __VA_ARGS__))
4665 #define REFL_DETAIL_FOR_EACH_18(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_17
(what, __VA_ARGS__))
4666 #define REFL_DETAIL_FOR_EACH_19(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_18
(what, __VA_ARGS__))
4667 #define REFL_DETAIL_FOR_EACH_20(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_19
(what, __VA_ARGS__))
4668 #define REFL_DETAIL_FOR_EACH_21(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_20
(what, __VA_ARGS__))
4669 #define REFL_DETAIL_FOR_EACH_22(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_21
(what, __VA_ARGS__))
4670 #define REFL_DETAIL_FOR_EACH_23(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_22
(what, __VA_ARGS__))
4671 #define REFL_DETAIL_FOR_EACH_24(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_23
(what, __VA_ARGS__))
4672 #define REFL_DETAIL_FOR_EACH_25(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_24
(what, __VA_ARGS__))
4673 #define REFL_DETAIL_FOR_EACH_26(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_25
(what, __VA_ARGS__))
4674 #define REFL_DETAIL_FOR_EACH_27(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_26
(what, __VA_ARGS__))
4675 #define REFL_DETAIL_FOR_EACH_28(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_27
(what, __VA_ARGS__))
4676 #define REFL_DETAIL_FOR_EACH_29(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_28
(what, __VA_ARGS__))
4677 #define REFL_DETAIL_FOR_EACH_30(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_29
(what, __VA_ARGS__))
4678 #define REFL_DETAIL_FOR_EACH_31(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_30
(what, __VA_ARGS__))
4679 #define REFL_DETAIL_FOR_EACH_32(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_31
(what, __VA_ARGS__))
4680 #define REFL_DETAIL_FOR_EACH_33(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_32
(what, __VA_ARGS__))
4681 #define REFL_DETAIL_FOR_EACH_34(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_33
(what, __VA_ARGS__))
4682 #define REFL_DETAIL_FOR_EACH_35(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_34
(what, __VA_ARGS__))
4683 #define REFL_DETAIL_FOR_EACH_36(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_35
(what, __VA_ARGS__))
4684 #define REFL_DETAIL_FOR_EACH_37(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_36
(what, __VA_ARGS__))
4685 #define REFL_DETAIL_FOR_EACH_38(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_37
(what, __VA_ARGS__))
4686 #define REFL_DETAIL_FOR_EACH_39(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_38
(what, __VA_ARGS__))
4687 #define REFL_DETAIL_FOR_EACH_40(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_39
(what, __VA_ARGS__))
4688 #define REFL_DETAIL_FOR_EACH_41(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_40
(what, __VA_ARGS__))
4689 #define REFL_DETAIL_FOR_EACH_42(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_41
(what, __VA_ARGS__))
4690 #define REFL_DETAIL_FOR_EACH_43(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_42
(what, __VA_ARGS__))
4691 #define REFL_DETAIL_FOR_EACH_44(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_43
(what, __VA_ARGS__))
4692 #define REFL_DETAIL_FOR_EACH_45(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_44
(what, __VA_ARGS__))
4693 #define REFL_DETAIL_FOR_EACH_46(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_45
(what, __VA_ARGS__))
4694 #define REFL_DETAIL_FOR_EACH_47(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_46
(what, __VA_ARGS__))
4695 #define REFL_DETAIL_FOR_EACH_48(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_47
(what, __VA_ARGS__))
4696 #define REFL_DETAIL_FOR_EACH_49(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_48
(what, __VA_ARGS__))
4697 #define REFL_DETAIL_FOR_EACH_50(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_49
(what, __VA_ARGS__))
4698 #define REFL_DETAIL_FOR_EACH_51(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_50
(what, __VA_ARGS__))
4699 #define REFL_DETAIL_FOR_EACH_52(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_51
(what, __VA_ARGS__))
4700 #define REFL_DETAIL_FOR_EACH_53(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_52
(what, __VA_ARGS__))
4701 #define REFL_DETAIL_FOR_EACH_54(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_53
(what, __VA_ARGS__))
4702 #define REFL_DETAIL_FOR_EACH_55(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_54
(what, __VA_ARGS__))
4703 #define REFL_DETAIL_FOR_EACH_56(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_55
(what, __VA_ARGS__))
4704 #define REFL_DETAIL_FOR_EACH_57(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_56
(what, __VA_ARGS__))
4705 #define REFL_DETAIL_FOR_EACH_58(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_57
(what, __VA_ARGS__))
4706 #define REFL_DETAIL_FOR_EACH_59(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_58
(what, __VA_ARGS__))
4707 #define REFL_DETAIL_FOR_EACH_60(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_59
(what, __VA_ARGS__))
4708 #define REFL_DETAIL_FOR_EACH_61(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_60
(what, __VA_ARGS__))
4709 #define REFL_DETAIL_FOR_EACH_62(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_61
(what, __VA_ARGS__))
4710 #define REFL_DETAIL_FOR_EACH_63(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_62
(what, __VA_ARGS__))
4711 #define REFL_DETAIL_FOR_EACH_64(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_63
(what, __VA_ARGS__))
4712 #define REFL_DETAIL_FOR_EACH_65(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_64
(what, __VA_ARGS__))
4713 #define REFL_DETAIL_FOR_EACH_66(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_65
(what, __VA_ARGS__))
4714 #define REFL_DETAIL_FOR_EACH_67(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_66
(what, __VA_ARGS__))
4715 #define REFL_DETAIL_FOR_EACH_68(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_67
(what, __VA_ARGS__))
4716 #define REFL_DETAIL_FOR_EACH_69(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_68
(what, __VA_ARGS__))
4717 #define REFL_DETAIL_FOR_EACH_70(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_69
(what, __VA_ARGS__))
4718 #define REFL_DETAIL_FOR_EACH_71(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_70
(what, __VA_ARGS__))
4719 #define REFL_DETAIL_FOR_EACH_72(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_71
(what, __VA_ARGS__))
4720 #define REFL_DETAIL_FOR_EACH_73(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_72
(what, __VA_ARGS__))
4721 #define REFL_DETAIL_FOR_EACH_74(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_73
(what, __VA_ARGS__))
4722 #define REFL_DETAIL_FOR_EACH_75(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_74
(what, __VA_ARGS__))
4723 #define REFL_DETAIL_FOR_EACH_76(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_75
(what, __VA_ARGS__))
4724 #define REFL_DETAIL_FOR_EACH_77(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_76
(what, __VA_ARGS__))
4725 #define REFL_DETAIL_FOR_EACH_78(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_77
(what, __VA_ARGS__))
4726 #define REFL_DETAIL_FOR_EACH_79(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_78
(what, __VA_ARGS__))
4727 #define REFL_DETAIL_FOR_EACH_80(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_79
(what, __VA_ARGS__))
4728 #define REFL_DETAIL_FOR_EACH_81(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_80
(what, __VA_ARGS__))
4729 #define REFL_DETAIL_FOR_EACH_82(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_81
(what, __VA_ARGS__))
4730 #define REFL_DETAIL_FOR_EACH_83(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_82
(what, __VA_ARGS__))
4731 #define REFL_DETAIL_FOR_EACH_84(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_83
(what, __VA_ARGS__))
4732 #define REFL_DETAIL_FOR_EACH_85(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_84
(what, __VA_ARGS__))
4733 #define REFL_DETAIL_FOR_EACH_86(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_85
(what, __VA_ARGS__))
4734 #define REFL_DETAIL_FOR_EACH_87(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_86
(what, __VA_ARGS__))
4735 #define REFL_DETAIL_FOR_EACH_88(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_87
(what, __VA_ARGS__))
4736 #define REFL_DETAIL_FOR_EACH_89(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_88
(what, __VA_ARGS__))
4737 #define REFL_DETAIL_FOR_EACH_90(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_89
(what, __VA_ARGS__))
4738 #define REFL_DETAIL_FOR_EACH_91(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_90
(what, __VA_ARGS__))
4739 #define REFL_DETAIL_FOR_EACH_92(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_91
(what, __VA_ARGS__))
4740 #define REFL_DETAIL_FOR_EACH_93(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_92
(what, __VA_ARGS__))
4741 #define REFL_DETAIL_FOR_EACH_94(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_93
(what, __VA_ARGS__))
4742 #define REFL_DETAIL_FOR_EACH_95(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_94
(what, __VA_ARGS__))
4743 #define REFL_DETAIL_FOR_EACH_96(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_95
(what, __VA_ARGS__))
4744 #define REFL_DETAIL_FOR_EACH_97(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_96
(what, __VA_ARGS__))
4745 #define REFL_DETAIL_FOR_EACH_98(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_97
(what, __VA_ARGS__))
4746 #define REFL_DETAIL_FOR_EACH_99(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_98
(what, __VA_ARGS__))
4747 #define REFL_DETAIL_FOR_EACH_100(what, x, ...) what(x) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_99
(what, __VA_ARGS__))
4749 #define REFL_DETAIL_FOR_EACH_NARG(...) REFL_DETAIL_FOR_EACH_NARG_
(__VA_ARGS__, REFL_DETAIL_FOR_EACH_RSEQ_N
())
4750 #define REFL_DETAIL_FOR_EACH_NARG_(...) REFL_DETAIL_EXPAND
(REFL_DETAIL_FOR_EACH_ARG_N
(__VA_ARGS__))
4751 #define REFL_DETAIL_FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, N, ...) N
4752 #define REFL_DETAIL_FOR_EACH_RSEQ_N() 100
, 99
, 98
, 97
, 96
, 95
, 94
, 93
, 92
, 91
, 90
, 89
, 88
, 87
, 86
, 85
, 84
, 83
, 82
, 81
, 80
, 79
, 78
, 77
, 76
, 75
, 74
, 73
, 72
, 71
, 70
, 69
, 68
, 67
, 66
, 65
, 64
, 63
, 62
, 61
, 60
, 59
, 58
, 57
, 56
, 55
, 54
, 53
, 52
, 51
, 50
, 49
, 48
, 47
, 46
, 45
, 44
, 43
, 42
, 41
, 40
, 39
, 38
, 37
, 36
, 35
, 34
, 33
, 32
, 31
, 30
, 29
, 28
, 27
, 26
, 25
, 24
, 23
, 22
, 21
, 20
, 19
, 18
, 17
, 16
, 15
, 14
, 13
, 12
, 11
, 10
, 9
, 8
, 7
, 6
, 5
, 4
, 3
, 2
, 1
, 0
4753 #define REFL_DETAIL_CONCATENATE(x, y) x##y
4754 #define REFL_DETAIL_FOR_EACH_(N, what, ...) REFL_DETAIL_EXPAND
(REFL_DETAIL_CONCATENATE
(REFL_DETAIL_FOR_EACH_
, N)(what, __VA_ARGS__))
4755 #define REFL_DETAIL_FOR_EACH(what, ...) REFL_DETAIL_FOR_EACH_
(REFL_DETAIL_FOR_EACH_NARG
(__VA_ARGS__), what, __VA_ARGS__)
4760 #ifdef __INTELLISENSE__
4762 #define REFL_DETAIL_EX_1_type(X, ...) REFL_TYPE(X)
4763 #define REFL_DETAIL_EX_1_template(X, Y, ...) REFL_TEMPLATE(X, Y)
4764 #define REFL_DETAIL_EX_1_field(X, ...) REFL_FIELD(X)
4765 #define REFL_DETAIL_EX_1_func(X, ...) REFL_FUNC(X)
4769 #define REFL_DETAIL_EX_1_type(...) REFL_DETAIL_EX_EXPAND
(REFL_DETAIL_EX_DEFER
(REFL_TYPE)(__VA_ARGS__))
4770 #define REFL_DETAIL_EX_1_template(...) REFL_DETAIL_EX_EXPAND
(REFL_DETAIL_EX_DEFER
(REFL_TEMPLATE)(__VA_ARGS__))
4771 #define REFL_DETAIL_EX_1_field(...) REFL_DETAIL_EX_EXPAND
(REFL_DETAIL_EX_DEFER
(REFL_FIELD
)(__VA_ARGS__))
4772 #define REFL_DETAIL_EX_1_func(...) REFL_DETAIL_EX_EXPAND
(REFL_DETAIL_EX_DEFER
(REFL_FUNC
)(__VA_ARGS__))
4776 #define REFL_DETAIL_EX_(Specifier, ...) REFL_DETAIL_EX_1_##Specifier __VA_ARGS__
4778 #define REFL_DETAIL_EX_EMPTY()
4779 #define REFL_DETAIL_EX_DEFER(Id) Id REFL_DETAIL_EX_EMPTY
()
4780 #define REFL_DETAIL_EX_EXPAND(...) __VA_ARGS__
4782 #define REFL_DETAIL_EX_END() REFL_END
4784 #define REFL_AUTO(...) REFL_DETAIL_FOR_EACH
(REFL_DETAIL_EX_
, __VA_ARGS__) REFL_DETAIL_EX_EXPAND
(REFL_DETAIL_EX_DEFER
(REFL_DETAIL_EX_END
)())