Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
reflect.hpp
Go to the documentation of this file.
1#pragma once
9#include <fc/utility.hpp>
10#include <boost/lexical_cast.hpp>
11#include <boost/preprocessor/seq/for_each.hpp>
12#include <boost/preprocessor/seq/enum.hpp>
13#include <boost/preprocessor/seq/size.hpp>
14#include <boost/preprocessor/seq/seq.hpp>
15#include <boost/preprocessor/stringize.hpp>
16#include <stdint.h>
17#include <string.h>
18
20
21namespace fc {
22
32template<typename T>
33struct reflector{
34 typedef T type;
37
80 #ifdef DOXYGEN
81 template<typename Visitor>
82 static inline void visit( const Visitor& v );
83 #endif // DOXYGEN
84};
85
86void throw_bad_enum_cast( int64_t i, const char* e );
87void throw_bad_enum_cast( const char* k, const char* e );
88
89template<typename C>
91private:
92 template<typename T>
93 static auto test( int ) -> decltype( std::declval<T>().reflector_init(), std::true_type() ) { return {}; }
94 template<typename>
95 static std::false_type test( long ) { return {}; }
96public:
97 static constexpr bool value = std::is_same<decltype( test<C>( 0 ) ), std::true_type>::value;
98};
99
100struct reflect_init {};
101
102template <typename Class>
104 explicit reflector_init_visitor( Class& c )
105 : obj(c) {}
106
107 void reflector_init() const {
108 reflect_init( obj );
109 }
111 reflect_init( obj );
112 }
113
114 private:
115
116 // 0 matches int if Class derived from reflect_init (SFINAE)
117 template<class T>
118 typename std::enable_if<std::is_base_of<fc::reflect_init, T>::value>::type
119 init_imp(T& t) {
120 t.reflector_init();
121 }
122
123 // SFINAE if Class not derived from reflect_init
124 template<class T>
125 typename std::enable_if<not std::is_base_of<fc::reflect_init, T>::value>::type
126 init_imp(T& t) {}
127
128 template<typename T>
129 auto reflect_init(T& t) -> decltype(init_imp(t), void()) {
130 init_imp(t);
131 }
132
133 protected:
134 Class& obj;
135};
136
137} // namespace fc
138
139
140#ifndef DOXYGEN
141
142#define FC_REFLECT_VISIT_BASE(r, visitor, base) \
143 fc::reflector<base>::visit_base( visitor );
144
145
146#ifndef _MSC_VER
147 #define FC_TEMPLATE template
148#else
149 // Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name
150 #pragma warning( disable: 4482 )
151 #define FC_TEMPLATE
152#endif
153
154#define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
155{ typedef decltype((static_cast<type*>(nullptr))->elem) member_type; \
156 visitor.FC_TEMPLATE operator()<member_type,type,&type::elem>( BOOST_PP_STRINGIZE(elem) ); \
157}
158
159
160#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
161 OP fc::reflector<elem>::total_member_count
162
163#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \
164 OP 1
165
166#define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
167template<typename Visitor>\
168static inline void visit_base( Visitor&& v ) { \
169 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
170 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
171} \
172template<typename Visitor>\
173static inline void visit( Visitor&& v ) { \
174 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
175 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
176 init( std::forward<Visitor>(v) ); \
177}
178
179#endif // DOXYGEN
180
181
182#define FC_REFLECT_VISIT_ENUM( r, enum_type, elem ) \
183 v.operator()(BOOST_PP_STRINGIZE(elem), int64_t(enum_type::elem) );
184#define FC_REFLECT_ENUM_TO_STRING( r, enum_type, elem ) \
185 case enum_type::elem: return BOOST_PP_STRINGIZE(elem);
186#define FC_REFLECT_ENUM_TO_FC_STRING( r, enum_type, elem ) \
187 case enum_type::elem: return fc::string(BOOST_PP_STRINGIZE(elem));
188
189#define FC_REFLECT_ENUM_FROM_STRING( r, enum_type, elem ) \
190 if( strcmp( s, BOOST_PP_STRINGIZE(elem) ) == 0 ) return enum_type::elem;
191#define FC_REFLECT_ENUM_FROM_STRING_CASE( r, enum_type, elem ) \
192 case enum_type::elem:
193
194#define FC_REFLECT_ENUM( ENUM, FIELDS ) \
195namespace fc { \
196template<> struct reflector<ENUM> { \
197 typedef fc::true_type is_defined; \
198 typedef fc::true_type is_enum; \
199 static const char* to_string(ENUM elem) { \
200 switch( elem ) { \
201 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, ENUM, FIELDS ) \
202 default: \
203 fc::throw_bad_enum_cast( fc::to_string(int64_t(elem)).c_str(), BOOST_PP_STRINGIZE(ENUM) ); \
204 }\
205 return nullptr; \
206 } \
207 static const char* to_string(int64_t i) { \
208 return to_string(ENUM(i)); \
209 } \
210 static fc::string to_fc_string(ENUM elem) { \
211 switch( elem ) { \
212 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_FC_STRING, ENUM, FIELDS ) \
213 } \
214 return fc::to_string(int64_t(elem)); \
215 } \
216 static fc::string to_fc_string(int64_t i) { \
217 return to_fc_string(ENUM(i)); \
218 } \
219 static ENUM from_int(int64_t i) { \
220 ENUM e = ENUM(i); \
221 switch( e ) \
222 { \
223 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING_CASE, ENUM, FIELDS ) \
224 break; \
225 default: \
226 fc::throw_bad_enum_cast( i, BOOST_PP_STRINGIZE(ENUM) ); \
227 } \
228 return e;\
229 } \
230 static ENUM from_string( const char* s ) { \
231 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING, ENUM, FIELDS ) \
232 int64_t i = 0; \
233 try \
234 { \
235 i = boost::lexical_cast<int64_t>(s); \
236 } \
237 catch( const boost::bad_lexical_cast& e ) \
238 { \
239 fc::throw_bad_enum_cast( s, BOOST_PP_STRINGIZE(ENUM) ); \
240 } \
241 return from_int(i); \
242 } \
243 template< typename Visitor > \
244 static void visit( Visitor& v ) \
245 { \
246 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_ENUM, ENUM, FIELDS ) \
247 } \
248}; \
249template<> struct get_typename<ENUM> { static const char* name() { return BOOST_PP_STRINGIZE(ENUM); } }; \
250}
251
252/* Note: FC_REFLECT_ENUM previously defined this function, but I don't think it ever
253 * did what we expected it to do. I've disabled it for now.
254 *
255 * template<typename Visitor> \
256 * static inline void visit( const Visitor& v ) { \
257 * BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_ENUM, ENUM, FIELDS ) \
258 * }\
259 */
260
270#define FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \
271namespace fc { \
272 template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
273template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
274 typedef TYPE type; \
275 typedef fc::true_type is_defined; \
276 typedef fc::false_type is_enum; \
277 template<typename Visitor> \
278 static auto init_imp(Visitor&& v, int) -> decltype(std::forward<Visitor>(v).reflector_init(), void()) { \
279 std::forward<Visitor>(v).reflector_init(); \
280 } \
281 template<typename Visitor> \
282 static auto init_imp(Visitor&& v, long) -> decltype(v, void()) {} \
283 template<typename Visitor> \
284 static auto init(Visitor&& v) -> decltype(init_imp(std::forward<Visitor>(v), 0), void()) { \
285 init_imp(std::forward<Visitor>(v), 0); \
286 } \
287 enum member_count_enum { \
288 local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\
289 total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
290 }; \
291 FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
292 static_assert( not fc::has_reflector_init<TYPE>::value || \
293 std::is_base_of<fc::reflect_init, TYPE>::value, "must derive from fc::reflect_init" ); \
294 static_assert( not std::is_base_of<fc::reflect_init, TYPE>::value || \
295 fc::has_reflector_init<TYPE>::value, "must provide reflector_init() method" ); \
296}; }
297
298#define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \
299 FC_REFLECT_DERIVED_TEMPLATE( (), TYPE, INHERITS, MEMBERS )
300
301//BOOST_PP_SEQ_SIZE(MEMBERS),
302
311#define FC_REFLECT( TYPE, MEMBERS ) \
312 FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
313
314#define FC_REFLECT_TEMPLATE( TEMPLATE_ARGS, TYPE, MEMBERS ) \
315 FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
316
317#define FC_REFLECT_EMPTY( TYPE ) \
318 FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, BOOST_PP_SEQ_NIL )
319
320#define FC_REFLECT_TYPENAME( TYPE ) \
321namespace fc { \
322 template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
323}
namespace sysio::chain
Definition authority.cpp:3
void throw_bad_enum_cast(int64_t i, const char *e)
#define T(meth, val, expected)
signed __int64 int64_t
Definition stdint.h:135
static constexpr bool value
Definition reflect.hpp:97
void reflector_init() const
Definition reflect.hpp:107
defines visit functions for T Unless this is specialized, visit() will not be defined for T.
Definition reflect.hpp:33
fc::false_type is_defined
Definition reflect.hpp:35
fc::false_type is_enum
Definition reflect.hpp:36