10 #ifndef EMP_REFLECTION_H 11 #define EMP_REFLECTION_H 23 #define EMP_CREATE_METHOD_FALLBACK(NAME, METHOD, FALLBACK) \ 24 namespace internal { \ 25 template <class T, class... ARGS> \ 26 auto EMPCall_ ## NAME(emp::bool_decoy<decltype(&T::METHOD)>, T & target, ARGS &&... args) \ 27 { return target.METHOD(std::forward<ARGS>(args)...); } \ 28 template <class T, class... ARGS> \ 29 auto EMPCall_ ## NAME(int, T & target, ARGS &&... args) \ 30 { return FALLBACK(target, std::forward<ARGS>(args)...); } \ 32 template <class T, class... ARGS> auto NAME(T & target, ARGS &&... args) { \ 33 return internal::EMPCall_ ## NAME(true, target, std::forward<ARGS>(args)...); \ 34 } int ignore_semicolon_to_follow_ ## NAME = 0 39 #define EMP_CREATE_OPTIONAL_METHOD(NAME, METHOD) \ 40 template <typename T, typename... ARGS> \ 41 void EMPCall_ ## NAME(emp::bool_decoy<decltype(&T::METHOD)>, T & target, ARGS &&... args) \ 42 { target.METHOD(std::forward<ARGS>(args)...); } \ 43 template <typename T, typename... ARGS> \ 44 void EMPCall_ ## NAME(int, T&, ARGS...) {;} \ 45 template <typename T, typename... ARGS> void NAME(T & target, ARGS &&... args) { \ 46 EMPCall_ ## NAME(true, target, std::forward<ARGS>(args)...); \ 47 } int ignore_semicolon_to_follow_ ## NAME = 0 52 #define EMP_CREATE_METHOD_FALLBACK_VAL(NAME, METHOD, DEFAULT) \ 53 namespace internal { \ 54 template <class T, class... ARGS> \ 55 auto EMPCall_ ## NAME(emp::bool_decoy<decltype(&T::METHOD)>, T & target, ARGS &&... args) \ 56 { return target.METHOD(std::forward<ARGS>(args)...); } \ 57 auto EMPCall_ ## NAME(...) \ 60 template <class T, class... ARGS> auto NAME(T & target, ARGS &&... args) { \ 61 return internal::EMPCall_ ## NAME(true, target, std::forward<ARGS>(args)...); \ 62 } int ignore_semicolon_to_follow_ ## NAME = 0 69 #define EMP_CREATE_EVAL_SELECT(NEW_NAME, TEST, RTYPE, EVAL1, EVAL2) \ 70 template <typename... ARG_TYPES> \ 71 RTYPE internal__RelayCall_ ## NEW_NAME( \ 72 emp::bool_decoy<decltype(TEST)>, \ 73 ARG_TYPES... args) { \ 74 return EVAL1(args...); \ 76 template <typename... ARG_TYPES> \ 77 RTYPE internal__RelayCall_ ## NEW_NAME(int, ARG_TYPES... args) { \ 78 return EVAL2(args...); \ 80 template <typename... ARG_TYPES> \ 81 RTYPE NEW_NAME(ARG_TYPES... args) { \ 82 return internal__RelayCall_ ## NEW_NAME(true, args...); \ 83 } int ignore_semicolon_to_follow_ ## NEW_NAME = 0 99 #define EMP_SETUP_TYPE_SELECTOR(NAME, MEMBER) \ 100 template <typename T> using EMPDetect_ ## NAME = decltype(T::MEMBER); \ 101 template <typename... Ts> \ 102 using NAME = typename emp::TypePack<Ts...>::template find_t<EMPDetect_ ## NAME>; 116 #define EMP_CHOOSE_MEMBER_TYPE(NAME, MEMBER, FALLBACK_T, ...) \ 117 template <typename EMP_T> using EMP_Filter_ ## NAME = typename EMP_T::MEMBER; \ 118 struct EMP_Fallback_ ## NAME { using MEMBER = FALLBACK_T; }; \ 119 using NAME = typename emp::TypePack<__VA_ARGS__, EMP_Fallback_ ## NAME> \ 120 ::template find_t<EMP_Filter_ ## NAME>::MEMBER; 127 #define EMP_IMPL_TYPE_HAS_MEMBER(FUN, LEVEL, MBR) \ 128 template <typename EMP__T> static \ 129 auto FUN ## _impl(emp::sfinae_decoy<LEVEL, decltype(std::declval<EMP__T>().MBR)>) \ 130 -> decltype(std::declval<EMP__T>().MBR) 132 #define EMP_IMPL_TYPE_HAS_TYPE(FUN, LEVEL, TYPE) \ 133 template <typename EMP__T> static \ 134 auto FUN ## _impl(emp::sfinae_decoy<LEVEL, typename EMP__T::TYPE) \ 137 #define EMP_IMPL_TYPE_DEFAULT(FUN, LEVEL, DEFAULT) \ 138 template <typename EMP__T> static DEFAULT FUN ## _impl(LEVEL) 140 #define EMP_ADD_TYPE_FROM_MEMBER(NEW_TYPE, BASE_TYPE, MEMBER, DEFAULT) \ 141 EMP_IMPL_TYPE_HAS_MEMBER(EMP_DETECT_ ## NEW_TYPE, bool, MEMBER); \ 142 EMP_IMPL_TYPE_DEFAULT(EMP_DETECT_ ## NEW_TYPE, int, DEFAULT); \ 143 using NEW_TYPE = decltype(EMP_DETECT_ ## NEW_TYPE ## _impl<BASE_TYPE>(true)) 145 #define EMP_ADD_TYPE_FROM_TYPE(NEW_TYPE, BASE_TYPE, TYPE, DEFAULT) \ 146 EMP_IMPL_TYPE_HAS_TYPE(EMP_DETECT_ ## NEW_TYPE, bool, TYPE); \ 147 EMP_IMPL_TYPE_DEFAULT(EMP_DETECT_ ## NEW_TYPE, int, DEFAULT); \ 148 using NEW_TYPE = decltype(EMP_DETECT_ ## NEW_TYPE ## _impl<BASE_TYPE>(true)) 150 #define EMP_ADD_TYPE_FROM_MEMBER_OR_TYPE(NEW_TYPE, BASE_TYPE, MEMBER, TYPE, DEFAULT) \ 151 EMP_IMPL_TYPE_HAS_MEMBER(EMP_DETECT_ ## NEW_TYPE, bool, MEMBER); \ 152 EMP_IMPL_TYPE_HAS_TYPE(EMP_DETECT_ ## NEW_TYPE, int, TYPE); \ 153 EMP_IMPL_TYPE_DEFAULT(EMP_DETECT_ ## NEW_TYPE, ..., DEFAULT); \ 154 using NEW_TYPE = decltype(EMP_DETECT_ ## NEW_TYPE ## _impl<BASE_TYPE>(true)) 156 #define EMP_ADD_TYPE_FROM_TYPE_OR_MEMBER(NEW_TYPE, BASE_TYPE, TYPE, MEMBER, DEFAULT) \ 157 EMP_IMPL_TYPE_HAS_TYPE(EMP_DETECT_ ## NEW_TYPE, bool, TYPE); \ 158 EMP_IMPL_TYPE_HAS_MEMBER(EMP_DETECT_ ## NEW_TYPE, int, MEMBER); \ 159 EMP_IMPL_TYPE_DEFAULT(EMP_DETECT_ ## NEW_TYPE, ..., DEFAULT); \ 160 using NEW_TYPE = decltype(EMP_DETECT_ ## NEW_TYPE ## _impl<BASE_TYPE>(true)) 167 template <
typename RETURN,
typename... FUN_ARGS>
169 template <
typename... EXTRA_ARGS>
170 static RETURN
Call(std::function<RETURN(FUN_ARGS...)> fun, FUN_ARGS... args, EXTRA_ARGS...) {
177 template <
typename RETURN,
typename... FUN_ARGS,
typename... CALL_ARGS>
178 auto SubsetCall(std::function<RETURN(FUN_ARGS...)> fun, CALL_ARGS... args) -> RETURN {
185 template<
typename T,
bool match_ok >
struct EMP_eval_type { };
186 template<
typename T>
struct EMP_eval_type<T,true> {
using type = T; };
192 template <
typename T,
template <
typename...>
class FILTER>
193 using type_if =
typename internal::EMP_eval_type< T, FILTER<T>::value >::type;
static RETURN Call(std::function< RETURN(FUN_ARGS...)> fun, FUN_ARGS...args, EXTRA_ARGS...)
Definition: reflection.h:170
A set of types that can be manipulated at compile time (good for metaprogramming) ...
typename internal::EMP_eval_type< T, FILTER< T >::value >::type type_if
Definition: reflection.h:193
If we are in emscripten, make sure to include the header.
Definition: array.h:37
auto SubsetCall(std::function< RETURN(FUN_ARGS...)> fun, CALL_ARGS...args) -> RETURN
Identify the number of parameters in a function and pass in correct number of argument.
Definition: reflection.h:178
Definition: reflection.h:168