diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 45efbe05d..5a97a8ee9 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -87,6 +87,9 @@ void throw_bad_enum_cast( const char* k, const char* e ); visitor.TEMPLATE operator()( BOOST_PP_STRINGIZE(elem) ); \ } +#define FC_REFLECT_VISIT_MEMBER_I( r, visitor, I, elem ) \ + case I: FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) break; + #define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ OP fc::reflector::total_member_count @@ -99,6 +102,13 @@ template\ static inline void visit( const Visitor& v ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \ +}\ +template\ +static inline void visit_local_member( const Visitor& v, IndexType index ) { \ + switch( index ) {\ + BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_VISIT_MEMBER_I, v, MEMBERS ) \ + default: break;\ + }\ } #define FC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \ diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 88efedad7..1b2628bd8 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -10,6 +10,8 @@ * **/ #pragma once + +#include #include #include #include @@ -176,6 +178,36 @@ struct type_info<> { } // namespace impl +template +std::vector> init_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_wrappers() +{ + std::vector> result + = init_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + +template +std::vector> init_const_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_const_wrappers() +{ + std::vector> result + = init_const_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + template class static_variant { static_assert(impl::type_info::no_reference_types, "Reference types are not permitted in static_variant."); @@ -308,22 +340,54 @@ class static_variant { } template typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); } template typename visitor::result_type visit(const visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); + } + + template + static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) + { + static auto wrappers = init_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) + { + static auto wrappers = init_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) + { + static auto wrappers = init_const_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) + { + static auto wrappers = init_const_wrappers(); + FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); } static int count() { return impl::type_info::count; } diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 343a64862..455a4f445 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -92,6 +92,8 @@ namespace fc void to_variant( const uint64_t& var, variant& vo, uint32_t max_depth = 1 ); void to_variant( const int64_t& var, variant& vo, uint32_t max_depth = 1 ); + void to_variant( const bool& var, variant& vo, uint32_t max_depth = 1 ); + void to_variant( const variant_object& var, variant& vo, uint32_t max_depth ); void from_variant( const variant& var, variant_object& vo, uint32_t max_depth ); void to_variant( const mutable_variant_object& var, variant& vo, uint32_t max_depth ); diff --git a/src/variant.cpp b/src/variant.cpp index 31204d486..2ee8256ef 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -629,6 +629,7 @@ void from_variant( const variant& var, uint64_t& vo, uint32_t max_depth ) vo = var.as_uint64(); } +void to_variant( const bool& var, variant& vo, uint32_t max_depth ) { vo = uint64_t(var); } void from_variant( const variant& var, bool& vo, uint32_t max_depth ) { vo = var.as_bool(); diff --git a/tests/stacktrace_test.cpp b/tests/stacktrace_test.cpp index baafa7669..bc710a5c1 100644 --- a/tests/stacktrace_test.cpp +++ b/tests/stacktrace_test.cpp @@ -1,9 +1,15 @@ #include +#include + #include + #include +#include #include +#include + BOOST_AUTO_TEST_SUITE(fc_stacktrace) BOOST_AUTO_TEST_CASE(stacktrace_test) @@ -40,6 +46,38 @@ BOOST_AUTO_TEST_CASE(threaded_stacktrace_test) #endif } +#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 +class _svdt_visitor +{ +public: + typedef std::string result_type; + std::string operator()( int64_t i )const + { + std::stringstream ss; + fc::print_stacktrace(ss); + return ss.str(); + } + template + std::string operator()( T i )const { return "Unexpected!"; } +}; + +BOOST_AUTO_TEST_CASE(static_variant_depth_test) +{ + int64_t i = 1; + fc::static_variant test(i); + + std::string stacktrace = test.visit( _svdt_visitor() ); + //std::cerr << stacktrace << "\n"; + std::vector lines; + boost::split( lines, stacktrace, boost::is_any_of("\n") ); + int count = 0; + for( const auto& line : lines ) + if( line.find("_svdt_visitor") != std::string::npos ) count++; + BOOST_CHECK_LT( 3, count ); // test.visit(), static_variant::visit, function object, visitor + BOOST_CHECK_GT( 8, count ); // some is implementation-dependent +} +#endif + /* this test causes a segfault on purpose to test the event handler BOOST_AUTO_TEST_CASE(cause_segfault) {