1
1
#pragma once
2
2
/* *
3
- * @file fc/reflect.hpp
3
+ * @file fc/reflect/reflect .hpp
4
4
*
5
5
* @brief Defines types and macros used to provide reflection.
6
6
*
18
18
#include < type_traits>
19
19
20
20
#include < fc/reflect/typename.hpp>
21
+ #include < fc/reflect/typelist.hpp>
21
22
22
23
namespace fc {
23
24
25
+ template <typename > struct reflector ;
26
+ namespace member_names {
27
+ // / A template which stores the name of the native member at a given index in a given class
28
+ template <typename Class, std::size_t index> struct member_name {
29
+ constexpr static const char * value = " Unknown member" ;
30
+ };
31
+ }
32
+
33
+ /* *
34
+ * @brief A template to store compile-time information about a field in a reflected struct
35
+ *
36
+ * @tparam Container The type of the struct or class containing the field
37
+ * @tparam Member The type of the field
38
+ * @tparam field A pointer-to-member for the reflected field
39
+ */
40
+ template <std::size_t Index, typename Container, typename Member, Member Container::*field>
41
+ struct field_reflection {
42
+ using container = Container;
43
+ using type = Member;
44
+ using reflector = fc::reflector<type>;
45
+ constexpr static std::size_t index = Index;
46
+ constexpr static bool is_derived = false ;
47
+ constexpr static type container::*pointer = field;
48
+
49
+ // / @brief Given a reference to the container type, get a reference to the field
50
+ static type& get (container& c) { return c.*field; }
51
+ static const type& get (const container& c) { return c.*field; }
52
+ // / @brief Get the name of the field
53
+ static const char * get_name () { return fc::member_names::member_name<container, index >::value; }
54
+ };
55
+ // / Basically the same as @ref field_reflection, but for inherited fields
56
+ // / Note that inherited field reflections do not have an index field; indexes are for native fields only
57
+ template <std::size_t IndexInBase, typename Base, typename Derived, typename Member, Member Base::*field>
58
+ struct inherited_field_reflection {
59
+ using container = Derived;
60
+ using field_container = Base;
61
+ using type = Member;
62
+ using reflector = fc::reflector<type>;
63
+ constexpr static std::size_t index_in_base = IndexInBase;
64
+ constexpr static bool is_derived = true ;
65
+ constexpr static type field_container::*pointer = field;
66
+
67
+ static type& get (container& c) {
68
+ // And we need a distinct inherited_field_reflection type because this conversion can't be done statically
69
+ type container::* derived_field = field;
70
+ return c.*derived_field;
71
+ }
72
+ static const type& get (const container& c) {
73
+ type container::* derived_field = field;
74
+ return c.*derived_field;
75
+ }
76
+ static const char * get_name () {
77
+ using Reflector = typename fc::reflector<Base>::native_members::template at<IndexInBase>;
78
+ return Reflector::get_name ();
79
+ }
80
+ };
81
+
82
+ namespace impl {
83
+ // / Helper template to create a @ref field_reflection without any commas (makes it macro-friendly)
84
+ template <typename Container>
85
+ struct Reflect_type {
86
+ template <typename Member>
87
+ struct with_field_type {
88
+ template <std::size_t Index>
89
+ struct at_index {
90
+ template <Member Container::*field>
91
+ struct with_field_pointer {
92
+ using type = field_reflection<Index, Container, Member, field>;
93
+ };
94
+ };
95
+ };
96
+ };
97
+ // / Template to make a transformer of a @ref field_reflection from a base class to a derived class
98
+ template <typename Derived>
99
+ struct Derivation_reflection_transformer {
100
+ template <typename > struct transform ;
101
+ template <std::size_t IndexInBase, typename BaseContainer, typename Member, Member BaseContainer::*field>
102
+ struct transform <field_reflection<IndexInBase, BaseContainer, Member, field>> {
103
+ using type = inherited_field_reflection<IndexInBase, BaseContainer, Derived, Member, field>;
104
+ };
105
+ template <std::size_t IndexInBase, typename BaseContainer, typename IntermediateContainer,
106
+ typename Member, Member BaseContainer::*field>
107
+ struct transform <inherited_field_reflection<IndexInBase, BaseContainer, IntermediateContainer, Member, field>> {
108
+ using type = inherited_field_reflection<IndexInBase, BaseContainer, Derived, Member, field>;
109
+ };
110
+ };
111
+ } // namespace impl
112
+
113
+ // / Macro to transform reflected fields of a base class to a derived class and concatenate them to a type list
114
+ #define FC_CONCAT_BASE_MEMBER_REFLECTIONS (r, derived, base ) \
115
+ ::add_list<typelist::transform<reflector<base>::members, impl::Derivation_reflection_transformer<derived>>>
116
+ // / Macro to concatenate a new @ref field_reflection to a typelist
117
+ #define FC_CONCAT_MEMBER_REFLECTION (r, container, idx, member ) \
118
+ ::add<typename impl::Reflect_type<container>::template with_field_type<decltype(container::member)> \
119
+ ::template at_index<idx> \
120
+ ::template with_field_pointer<&container::member>::type>
121
+ #define FC_REFLECT_MEMBER_NAME (r, container, idx, member ) \
122
+ template <> struct member_name <container, idx> { constexpr static const char * value = BOOST_PP_STRINGIZE(member); };
123
+ #define FC_REFLECT_TEMPLATE_MEMBER_NAME (r, data, idx, member ) \
124
+ template <BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_ELEM(0 , data))> struct member_name <BOOST_PP_SEQ_ELEM(1 , data), idx> { \
125
+ constexpr static const char * value = BOOST_PP_STRINGIZE(member); };
126
+ // / Macro to concatenate a new type to a typelist
127
+ #define FC_CONCAT_TYPE (r, x, TYPE ) ::add<TYPE>
128
+
24
129
/* *
25
130
* @brief defines visit functions for T
26
131
* Unless this is specialized, visit() will not be defined for T.
@@ -34,6 +139,14 @@ template<typename T>
34
139
struct reflector {
35
140
typedef T type;
36
141
typedef std::false_type is_defined;
142
+ // / A typelist with a @ref field_reflection for each native member (non-inherited) of the struct
143
+ using native_members = typelist::list<>;
144
+ // / A typelist with a @ref field_reflection for each inherited member of the struct
145
+ using inherited_members = typelist::list<>;
146
+ // / A typelist with a @ref field_reflection for each member of the struct, starting with inherited members
147
+ using members = typelist::list<>;
148
+ // / A typelist of base classes for this type
149
+ using base_classes = typelist::list<>;
37
150
38
151
/* *
39
152
* @tparam Visitor a function object of the form:
@@ -91,31 +204,11 @@ void throw_bad_enum_cast( const char* k, const char* e );
91
204
case I: FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) break ;
92
205
93
206
94
- #define FC_REFLECT_BASE_MEMBER_COUNT ( r, OP, elem ) \
95
- OP fc::reflector<elem>::total_member_count
96
-
97
- #define FC_REFLECT_MEMBER_COUNT ( r, OP, elem ) \
98
- OP 1
99
-
100
207
#define FC_REFLECT_DERIVED_IMPL_INLINE ( TYPE, INHERITS, MEMBERS ) \
101
208
template <typename Visitor>\
102
209
static inline void visit ( const Visitor& v ) { \
103
210
BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
104
211
BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
105
- }\
106
- template <typename Visitor, typename IndexType>\
107
- static inline void visit_local_member ( const Visitor& v, IndexType index ) { \
108
- switch ( index ) {\
109
- BOOST_PP_SEQ_FOR_EACH_I ( FC_REFLECT_VISIT_MEMBER_I, v, MEMBERS ) \
110
- default : break ;\
111
- }\
112
- }
113
-
114
- #define FC_REFLECT_DERIVED_IMPL_EXT ( TYPE, INHERITS, MEMBERS ) \
115
- template <typename Visitor>\
116
- void fc::reflector<TYPE>::visit( const Visitor& v ) { \
117
- BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
118
- BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
119
212
}
120
213
121
214
#endif // DOXYGEN
@@ -214,26 +307,50 @@ namespace fc { \
214
307
template <> struct reflector <TYPE> {\
215
308
typedef TYPE type; \
216
309
typedef std::true_type is_defined; \
310
+ using native_members = \
311
+ typename typelist::builder<>::type \
312
+ BOOST_PP_SEQ_FOR_EACH_I ( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \
313
+ using inherited_members = \
314
+ typename typelist::builder<>::type \
315
+ BOOST_PP_SEQ_FOR_EACH ( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \
316
+ using members = typename typelist::concat<inherited_members, native_members>::type; \
317
+ using base_classes = typename typelist::builder<>::type \
318
+ BOOST_PP_SEQ_FOR_EACH ( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
217
319
enum member_count_enum { \
218
- local_member_count = 0 BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ), \
219
- total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS ) \
320
+ local_member_count = typelist::length<native_members>(), \
321
+ total_member_count = typelist::length<members>() \
220
322
}; \
221
323
FC_REFLECT_DERIVED_IMPL_INLINE ( TYPE, INHERITS, MEMBERS ) \
222
- }; }
324
+ }; \
325
+ namespace member_names { \
326
+ BOOST_PP_SEQ_FOR_EACH_I ( FC_REFLECT_MEMBER_NAME, TYPE, MEMBERS ) \
327
+ } }
223
328
#define FC_REFLECT_DERIVED_TEMPLATE ( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \
224
329
namespace fc { \
225
- template <BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename <TYPE> { static const char * name () { return BOOST_PP_STRINGIZE (TYPE); } }; \
330
+ template <BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename <TYPE> { \
331
+ static const char * name () { return BOOST_PP_STRINGIZE (TYPE); } \
332
+ }; \
226
333
template <BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector <TYPE> {\
227
334
typedef TYPE type; \
228
335
typedef std::true_type is_defined; \
336
+ using native_members = \
337
+ typename typelist::builder<>::type \
338
+ BOOST_PP_SEQ_FOR_EACH_I ( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \
339
+ using inherited_members = \
340
+ typename typelist::builder<>::type \
341
+ BOOST_PP_SEQ_FOR_EACH ( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \
342
+ using members = typename typelist::concat<inherited_members, native_members>::type; \
343
+ using base_classes = typename typelist::builder<>::type \
344
+ BOOST_PP_SEQ_FOR_EACH ( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
229
345
enum member_count_enum { \
230
- local_member_count = 0 BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ), \
231
- total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS ) \
346
+ local_member_count = typelist::length<native_members>(), \
347
+ total_member_count = typelist::length<members>() \
232
348
}; \
233
349
FC_REFLECT_DERIVED_IMPL_INLINE ( TYPE, INHERITS, MEMBERS ) \
234
- }; }
235
-
236
- // BOOST_PP_SEQ_SIZE(MEMBERS),
350
+ }; \
351
+ namespace member_names { \
352
+ BOOST_PP_SEQ_FOR_EACH_I ( FC_REFLECT_TEMPLATE_MEMBER_NAME, (TEMPLATE_ARGS)(TYPE), MEMBERS ) \
353
+ } }
237
354
238
355
/* *
239
356
* @def FC_REFLECT(TYPE,MEMBERS)
@@ -244,7 +361,8 @@ template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
244
361
* @see FC_REFLECT_DERIVED
245
362
*/
246
363
#define FC_REFLECT ( TYPE, MEMBERS ) \
247
- FC_REFLECT_DERIVED ( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
364
+ FC_REFLECT_DERIVED ( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
365
+
248
366
249
367
#define FC_REFLECT_TEMPLATE ( TEMPLATE_ARGS, TYPE, MEMBERS ) \
250
368
FC_REFLECT_DERIVED_TEMPLATE ( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
@@ -257,25 +375,3 @@ namespace fc { \
257
375
template <> struct get_typename <TYPE> { static const char * name () { return BOOST_PP_STRINGIZE (TYPE); } }; \
258
376
}
259
377
260
- #define FC_REFLECT_FWD ( TYPE ) \
261
- namespace fc { \
262
- template <> struct get_typename <TYPE> { static const char * name () { return BOOST_PP_STRINGIZE (TYPE); } }; \
263
- template <> struct reflector <TYPE> {\
264
- typedef TYPE type; \
265
- typedef std::true_type is_defined; \
266
- enum member_count_enum { \
267
- local_member_count = BOOST_PP_SEQ_SIZE (MEMBERS), \
268
- total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH ( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
269
- }; \
270
- template <typename Visitor> static void visit ( const Visitor& v ); \
271
- }; }
272
-
273
-
274
- #define FC_REFLECT_DERIVED_IMPL ( TYPE, MEMBERS ) \
275
- FC_REFLECT_IMPL_DERIVED_EXT ( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
276
-
277
- #define FC_REFLECT_IMPL ( TYPE, MEMBERS ) \
278
- FC_REFLECT_DERIVED_IMPL_EXT ( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
279
-
280
-
281
-
0 commit comments