FC Updates from BitShares and myself #21
5 changed files with 119 additions and 4 deletions
|
|
@ -87,6 +87,9 @@ void throw_bad_enum_cast( const char* k, const char* e );
|
|||
visitor.TEMPLATE operator()<member_type,type,&type::elem>( 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<elem>::total_member_count
|
||||
|
|
@ -99,6 +102,13 @@ template<typename Visitor>\
|
|||
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<typename Visitor, typename IndexType>\
|
||||
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 ) \
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
*
|
||||
**/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
|
@ -176,6 +178,36 @@ struct type_info<> {
|
|||
|
||||
} // namespace impl
|
||||
|
||||
template<typename Visitor,typename Data>
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> init_wrappers()
|
||||
{
|
||||
return std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>>();
|
||||
}
|
||||
|
||||
template<typename Visitor,typename Data, typename T, typename ... Types>
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> init_wrappers()
|
||||
{
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> result
|
||||
= init_wrappers<Visitor,Data,Types...>();
|
||||
result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<T*>( d ) ); } );
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Visitor,typename Data>
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> init_const_wrappers()
|
||||
{
|
||||
return std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>>();
|
||||
}
|
||||
|
||||
template<typename Visitor,typename Data, typename T, typename ... Types>
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> init_const_wrappers()
|
||||
{
|
||||
std::vector<std::function<typename Visitor::result_type(Visitor&,Data)>> result
|
||||
= init_const_wrappers<Visitor,Data,Types...>();
|
||||
result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<const T*>( d ) ); } );
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
class static_variant {
|
||||
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
|
||||
|
|
@ -308,22 +340,54 @@ public:
|
|||
}
|
||||
template<typename visitor>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, visitor& v, void* data )
|
||||
{
|
||||
static auto wrappers = init_wrappers<visitor,void*,Types...>();
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data )
|
||||
{
|
||||
static auto wrappers = init_wrappers<const visitor,void*,Types...>();
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data )
|
||||
{
|
||||
static auto wrappers = init_const_wrappers<visitor,const void*,Types...>();
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data )
|
||||
{
|
||||
static auto wrappers = init_const_wrappers<const visitor,const void*,Types...>();
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
}
|
||||
|
||||
static int count() { return impl::type_info<Types...>::count; }
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <fc/stacktrace.hpp>
|
||||
#include <fc/static_variant.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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<typename T>
|
||||
std::string operator()( T i )const { return "Unexpected!"; }
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(static_variant_depth_test)
|
||||
{
|
||||
int64_t i = 1;
|
||||
fc::static_variant<uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t> test(i);
|
||||
|
||||
std::string stacktrace = test.visit( _svdt_visitor() );
|
||||
//std::cerr << stacktrace << "\n";
|
||||
std::vector<std::string> 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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue