// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "HAL/Platform.h" #include namespace PlainProps { template struct TCttiOf { using Type = decltype(CttiOfPtr((T*)nullptr)); }; template using CttiOf = typename TCttiOf::Type; ////////////////////////////////////////////////////////////////////////// // Private PP_REFLECT_XYZ helpers #define _PP_EXPAND(X) X #define _PP_NUM_ARGS_(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10, N, ...) N #define _PP_NUM_ARGS(...) _PP_EXPAND(_PP_NUM_ARGS_(__VA_ARGS__,10,9,8,7,6,5,4,3,2,1)) #define _PP_REFLECT_1( N, MACRO, NS, T, M) MACRO(N-1, NS, T, M) #define _PP_REFLECT_2( N, MACRO, NS, T, M, ...) MACRO(N-2, NS, T, M) _PP_REFLECT_1(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_3( N, MACRO, NS, T, M, ...) MACRO(N-3, NS, T, M) _PP_REFLECT_2(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_4( N, MACRO, NS, T, M, ...) MACRO(N-4, NS, T, M) _PP_REFLECT_3(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_5( N, MACRO, NS, T, M, ...) MACRO(N-5, NS, T, M) _PP_REFLECT_4(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_6( N, MACRO, NS, T, M, ...) MACRO(N-6, NS, T, M) _PP_REFLECT_5(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_7( N, MACRO, NS, T, M, ...) MACRO(N-7, NS, T, M) _PP_REFLECT_6(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_8( N, MACRO, NS, T, M, ...) MACRO(N-8, NS, T, M) _PP_REFLECT_7(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_9( N, MACRO, NS, T, M, ...) MACRO(N-9, NS, T, M) _PP_REFLECT_8(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_10(N, MACRO, NS, T, M, ...) MACRO(N-10, NS, T, M) _PP_REFLECT_9(N, MACRO, NS, T, __VA_ARGS__) #define _PP_REFLECT_THINGS(N, MACRO, ...) _PP_EXPAND(_PP_REFLECT_##N(N, MACRO, __VA_ARGS__)) #define _PP_REFLECT_ENUMERATOR(N, NS, T, C) { #C, Type::C }, #define _PP_REFLECT_ENUM_INNER(N, NS, T, ES) struct T##_Ctti { inline static constexpr char Name[] = #T; using Type = NS :: T; static constexpr int NumEnumerators = N; static constexpr struct { const char* Name; Type Constant; } Enumerators[] = { ES }; inline static constexpr char Namespace[] = #NS; }; T##_Ctti CttiOfPtr(T*); #define _PP_REFLECT_ENUM(N, NS, T, ...) _PP_REFLECT_ENUM_INNER(N, NS, T, _PP_EXPAND(_PP_REFLECT_THINGS(N, _PP_REFLECT_ENUMERATOR, NS, T, __VA_ARGS__))) #define _PP_REFLECT_STRUCT(N, NS, T, S, ...) PP_REFLECT_STRUCT_ONLY(N, NS, T, S) _PP_EXPAND(_PP_REFLECT_THINGS(N, PP_REFLECT_MEMBER, NS, T, __VA_ARGS__)) #define _PP_REFLECT_STRUCT_TEMPLATE(N, NS, T, S, ...) PP_REFLECT_STRUCT_TEMPLATE_ONLY(N, NS, T, S) _PP_EXPAND(_PP_REFLECT_THINGS(N, PP_REFLECT_TEMPLATE_MEMBER, NS, T, __VA_ARGS__)) ////////////////////////////////////////////////////////////////////////// #define PP_REFLECT_ENUM(NS, T, ...) _PP_REFLECT_ENUM(_PP_NUM_ARGS(__VA_ARGS__), NS, T, __VA_ARGS__) #define PP_REFLECT_STRUCT(NS, T, S, ...) _PP_REFLECT_STRUCT(_PP_NUM_ARGS(__VA_ARGS__), NS, T, S, __VA_ARGS__) #define PP_REFLECT_STRUCT_TEMPLATE(NS, T, S, ...) _PP_REFLECT_STRUCT_TEMPLATE(_PP_NUM_ARGS(__VA_ARGS__), NS, T, S, __VA_ARGS__) #define PP_NAME_STRUCT(NS, T) struct T##_Ctti { inline static constexpr char Name[] = #T; using Type = NS :: T; inline static constexpr char Namespace[] = #NS; }; T##_Ctti CttiOfPtr(T*); #define PP_NAME_STRUCT_TEMPLATE(NS, T) template struct T##_Ctti { inline static constexpr char Name[] = #T; using Type = NS :: T; using TemplateArgs = std::tuple; inline static constexpr char Namespace[] = #NS; }; template T##_Ctti CttiOfPtr(T*); // Alternate set of macros to reflect classes/structs with bitfield bool members, e.g. uint8 bOol : 1; #define PP_REFLECT_STRUCT_ONLY(N, NS, T, S) struct T##_Ctti { inline static constexpr char Name[] = #T; using Type = NS :: T; using Super = S; static constexpr int NumVars = N; template struct Var; inline static constexpr char Namespace[] = #NS; }; T##_Ctti CttiOfPtr(T*); #define PP_REFLECT_STRUCT_TEMPLATE_ONLY(N, NS, T, S) template struct T##_Ctti { inline static constexpr char Name[] = #T; using Type = NS :: T; using Super = S; using TemplateArgs = std::tuple; static constexpr int NumVars = N; template struct Var_; template using Var = Var_; inline static constexpr char Namespace[] = #NS; }; template T##_Ctti CttiOfPtr(T*); #define PP_REFLECT_MEMBER(N, NS, T, M) template<> struct T##_Ctti::Var { inline static constexpr char Name[] = #M; using Type = decltype(NS :: T :: M); static constexpr std::size_t Offset = offsetof(NS :: T, M); static constexpr auto Pointer = &NS :: T :: M; static constexpr int Index = N; }; #define PP_REFLECT_BIT_MEMBER(N, NS, T, M, BYTEOFFSET, BITOFFSET) template<> struct T##_Ctti::Var { inline static constexpr char Name[] = #M; using Type = decltype(NS :: T :: M); static constexpr std::size_t Offset = BYTEOFFSET; static constexpr int BitIndex = BITOFFSET; static constexpr int Index = N; }; #define PP_REFLECT_TEMPLATE_MEMBER(N, NS, T, M) template template struct T##_Ctti::Var_ { inline static constexpr char Name[] = #M; using Type = decltype(NS :: T :: M); static constexpr std::size_t Offset = offsetof(NS :: T, M); static constexpr auto Pointer = &NS :: T :: M; static constexpr int Index = N; }; #define PP_REFLECT_TEMPLATE_BIT_MEMBER todo ////////////////////////////////////////////////////////////////////////// // E.g. ForEachVar>([]() { printf(Var::Name); }); template static constexpr void ForEachVar(Fn&& Visitor) { constexpr int N = Ctti::NumVars; if constexpr (N > 0) Visitor.template operator()>(); if constexpr (N > 1) Visitor.template operator()>(); if constexpr (N > 2) Visitor.template operator()>(); if constexpr (N > 3) Visitor.template operator()>(); if constexpr (N > 4) Visitor.template operator()>(); if constexpr (N > 5) Visitor.template operator()>(); if constexpr (N > 6) Visitor.template operator()>(); if constexpr (N > 7) Visitor.template operator()>(); if constexpr (N > 8) Visitor.template operator()>(); if constexpr (N > 9) Visitor.template operator()>(); } ////////////////////////////////////////////////////////////////////////// template concept Templated = requires { typename Ctti::TemplateArgs; }; } // namespace PlainProps