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>
81 template<
typename Visitor>
82 static inline void visit(
const Visitor& v );
93 static auto test(
int ) ->
decltype( std::declval<T>().reflector_init(), std::true_type() ) {
return {}; }
95 static std::false_type test(
long ) {
return {}; }
97 static constexpr bool value = std::is_same<decltype( test<C>( 0 ) ), std::true_type>
::value;
102template <
typename Class>
118 typename std::enable_if<std::is_base_of<fc::reflect_init, T>::value>::type
125 typename std::enable_if<not std::is_base_of<fc::reflect_init, T>::value>::type
129 auto reflect_init(
T& t) ->
decltype(init_imp(t), void()) {
142#define FC_REFLECT_VISIT_BASE(r, visitor, base) \
143 fc::reflector<base>::visit_base( visitor );
147 #define FC_TEMPLATE template
150 #pragma warning( disable: 4482 )
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) ); \
160#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
161 OP fc::reflector<elem>::total_member_count
163#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \
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 ) \
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) ); \
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));
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:
194#define FC_REFLECT_ENUM( ENUM, FIELDS ) \
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) { \
201 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, ENUM, FIELDS ) \
203 fc::throw_bad_enum_cast( fc::to_string(int64_t(elem)).c_str(), BOOST_PP_STRINGIZE(ENUM) ); \
207 static const char* to_string(int64_t i) { \
208 return to_string(ENUM(i)); \
210 static fc::string to_fc_string(ENUM elem) { \
212 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_FC_STRING, ENUM, FIELDS ) \
214 return fc::to_string(int64_t(elem)); \
216 static fc::string to_fc_string(int64_t i) { \
217 return to_fc_string(ENUM(i)); \
219 static ENUM from_int(int64_t i) { \
223 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING_CASE, ENUM, FIELDS ) \
226 fc::throw_bad_enum_cast( i, BOOST_PP_STRINGIZE(ENUM) ); \
230 static ENUM from_string( const char* s ) { \
231 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING, ENUM, FIELDS ) \
235 i = boost::lexical_cast<int64_t>(s); \
237 catch( const boost::bad_lexical_cast& e ) \
239 fc::throw_bad_enum_cast( s, BOOST_PP_STRINGIZE(ENUM) ); \
241 return from_int(i); \
243 template< typename Visitor > \
244 static void visit( Visitor& v ) \
246 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_ENUM, ENUM, FIELDS ) \
249template<> struct get_typename<ENUM> { static const char* name() { return BOOST_PP_STRINGIZE(ENUM); } }; \
270#define FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \
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> {\
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(); \
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); \
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 )\
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" ); \
298#define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \
299 FC_REFLECT_DERIVED_TEMPLATE( (), TYPE, INHERITS, MEMBERS )
311#define FC_REFLECT( TYPE, MEMBERS ) \
312 FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
314#define FC_REFLECT_TEMPLATE( TEMPLATE_ARGS, TYPE, MEMBERS ) \
315 FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
317#define FC_REFLECT_EMPTY( TYPE ) \
318 FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, BOOST_PP_SEQ_NIL )
320#define FC_REFLECT_TYPENAME( TYPE ) \
322 template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
void throw_bad_enum_cast(int64_t i, const char *e)
#define T(meth, val, expected)
static constexpr bool value
void reflector_init() const
reflector_init_visitor(Class &c)
defines visit functions for T Unless this is specialized, visit() will not be defined for T.
fc::false_type is_defined