Empirical
reflection.h
Go to the documentation of this file.
1 
10 #ifndef EMP_REFLECTION_H
11 #define EMP_REFLECTION_H
12 
13 #include "meta.h"
14 #include "TypePack.h"
15 
22 
23 #define EMP_CREATE_METHOD_FALLBACK(NAME, METHOD, FALLBACK) \
24  namespace internal { \
25  template <class T, class... ARGS> /* T::METHOD exists! */ \
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> /* T::METHOD does NOT exist! */ \
29  auto EMPCall_ ## NAME(int, T & target, ARGS &&... args) \
30  { return FALLBACK(target, std::forward<ARGS>(args)...); } \
31  } \
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
35 
36 
38 
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
48 
49 
51 
52 #define EMP_CREATE_METHOD_FALLBACK_VAL(NAME, METHOD, DEFAULT) \
53 namespace internal { \
54  template <class T, class... ARGS> /* T::METHOD exists! */ \
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(...) /* T::METHOD does NOT exist! */ \
58  { return DEFAULT; } \
59 } \
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
63 
64 
68 
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...); \
75  } \
76  template <typename... ARG_TYPES> \
77  RTYPE internal__RelayCall_ ## NEW_NAME(int, ARG_TYPES... args) { \
78  return EVAL2(args...); \
79  } \
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
84 
85 
98 
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>;
103 
104 
115 
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;
121 
122 
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)
131 
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) \
135  -> EMP__T::TYPE
136 
137 #define EMP_IMPL_TYPE_DEFAULT(FUN, LEVEL, DEFAULT) \
138  template <typename EMP__T> static DEFAULT FUN ## _impl(LEVEL)
139 
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))
144 
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))
149 
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))
155 
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))
161 
162 
163 namespace emp {
164 
165  // Helper tools for SubsetCall.
166  namespace internal {
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...) {
171  return fun(args...);
172  }
173  };
174  }
175 
177  template <typename RETURN, typename... FUN_ARGS, typename... CALL_ARGS>
178  auto SubsetCall(std::function<RETURN(FUN_ARGS...)> fun, CALL_ARGS... args) -> RETURN {
180  }
181 
182 
183  // Helper tools for type_if.
184  namespace internal {
185  template< typename T, bool match_ok > struct EMP_eval_type { };
186  template< typename T> struct EMP_eval_type<T,true> { using type = T; }; // If match, define type!
187  }
188 
192  template <typename T, template <typename...> class FILTER>
193  using type_if = typename internal::EMP_eval_type< T, FILTER<T>::value >::type;
194 
195 }
196 #endif
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