From 3f4a4468e045df53e0a202fa798bb5c490916b13 Mon Sep 17 00:00:00 2001 From: pravin-battu Date: Fri, 16 Oct 2020 12:12:57 -0300 Subject: [PATCH] static variant update --- CMakeLists.txt | 1 + include/fc/static_variant.hpp | 182 ++++++++++++++++------------------ src/static_variant.cpp | 31 ++++++ 3 files changed, 115 insertions(+), 99 deletions(-) create mode 100644 src/static_variant.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd52180..1ae6502 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,7 @@ set( fc_sources src/variant.cpp src/exception.cpp src/variant_object.cpp + src/static_variant.cpp src/thread/thread.cpp src/thread/thread_specific.cpp src/thread/future.cpp diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index ed8c66f..aa753a3 100755 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -1,4 +1,5 @@ -/** This source adapted from https://github.com/kmicklas/variadic-static_variant + +/** This source adapted from https://github.com/kmicklas/variadic-static_variant Now available at https://github.com/kmicklas/variadic-variant. * * Copyright (C) 2013 Kenneth Micklas * @@ -13,21 +14,15 @@ #include #include #include - namespace fc { - // Implementation details, the user should not import this: namespace impl { - template struct storage_ops; - template struct position; - template struct type_info; - template struct copy_construct { @@ -40,7 +35,6 @@ struct copy_construct sv.init(v); } }; - template struct move_construct { @@ -53,25 +47,19 @@ struct move_construct sv.init( std::move(v) ); } }; - template struct storage_ops { static void del(int n, void *data) {} static void con(int n, void *data) {} - template static typename visitor::result_type apply(int n, void *data, visitor& v) {} - template static typename visitor::result_type apply(int n, void *data, const visitor& v) {} - template static typename visitor::result_type apply(int n, const void *data, visitor& v) {} - template static typename visitor::result_type apply(int n, const void *data, const visitor& v) {} }; - template struct storage_ops { static void del(int n, void *data) { @@ -82,32 +70,27 @@ struct storage_ops { if(n == N) new(reinterpret_cast(data)) T(); else storage_ops::con(n, data); } - template static typename visitor::result_type apply(int n, void *data, visitor& v) { if(n == N) return v(*reinterpret_cast(data)); else return storage_ops::apply(n, data, v); } - template static typename visitor::result_type apply(int n, void *data, const visitor& v) { if(n == N) return v(*reinterpret_cast(data)); else return storage_ops::apply(n, data, v); } - template static typename visitor::result_type apply(int n, const void *data, visitor& v) { if(n == N) return v(*reinterpret_cast(data)); else return storage_ops::apply(n, data, v); } - template static typename visitor::result_type apply(int n, const void *data, const visitor& v) { if(n == N) return v(*reinterpret_cast(data)); else return storage_ops::apply(n, data, v); } }; - template struct storage_ops { static void del(int n, void *data) { @@ -116,7 +99,6 @@ struct storage_ops { static void con(int n, void *data) { FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); } - template static typename visitor::result_type apply(int n, void *data, visitor& v) { FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); @@ -134,22 +116,18 @@ struct storage_ops { FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." ); } }; - template struct position { static const int pos = -1; }; - template struct position { static const int pos = 0; }; - template struct position { static const int pos = position::pos != -1 ? position::pos + 1 : -1; }; - template struct type_info { static const bool no_reference_types = false; @@ -157,7 +135,6 @@ struct type_info { static const size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); static const size_t count = 1 + type_info::count; }; - template struct type_info { static const bool no_reference_types = type_info::no_reference_types; @@ -165,7 +142,6 @@ struct type_info { static const size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); static const size_t count = 1 + type_info::count; }; - template<> struct type_info<> { static const bool no_reference_types = true; @@ -174,48 +150,94 @@ struct type_info<> { static const size_t size = 0; }; -} // namespace impl +template +size_t size( TTag ) +{ + return 0; +} +template +size_t size( TTag tag ) +{ + if (tag <= 0) + { + return sizeof(A); + } + + return size( --tag ); +} + + +class dynamic_storage +{ + char* storage; +public: + dynamic_storage(); + + ~dynamic_storage(); + + void* data() const; + + void alloc( size_t size ); + + void release(); +}; + +} // namespace impl template class static_variant { + using tag_type = int64_t; + static_assert(impl::type_info::no_reference_types, "Reference types are not permitted in static_variant."); static_assert(impl::type_info::no_duplicates, "static_variant type arguments contain duplicate types."); - int _tag; - char storage[impl::type_info::size]; - template + using type_in_typelist = typename std::enable_if::pos != -1, X>::type; // type is in typelist of static_variant. + + + int _tag; + impl::dynamic_storage storage; + template> void init(const X& x) { _tag = impl::position::pos; - new(storage) X(x); + storage.alloc( sizeof(X) ); + new(storage.data()) X(x); } - - template + template> void init(X&& x) { _tag = impl::position::pos; - new(storage) X( std::move(x) ); + storage.alloc( sizeof(X) ); + new(storage.data()) X( std::move(x) ); } + void init(tag_type tag) + { + FC_ASSERT( tag >= 0 ); + FC_ASSERT( tag < count() ); + _tag = tag; + storage.alloc( impl::size( tag ) ); + impl::storage_ops<0, Types...>::con(_tag, storage.data()); + } + + void clean() + { + impl::storage_ops<0, Types...>::del(_tag, storage.data() ); + storage.release(); + } template friend struct impl::copy_construct; template friend struct impl::move_construct; public: - template + template> struct tag { - static_assert( - impl::position::pos != -1, - "Type not in static_variant." - ); static const int value = impl::position::pos; }; static_variant() { - _tag = 0; - impl::storage_ops<0, Types...>::con(0, storage); - } - + init(0); + } template static_variant( const static_variant& cpy ) { @@ -225,46 +247,34 @@ public: { cpy.visit( impl::copy_construct(*this) ); } - static_variant( static_variant&& mv ) { mv.visit( impl::move_construct(*this) ); } - - template + template> static_variant(const X& v) { - static_assert( - impl::position::pos != -1, - "Type not in static_variant." - ); init(v); } ~static_variant() { - impl::storage_ops<0, Types...>::del(_tag, storage); + clean(); } - - - template + template> static_variant& operator=(const X& v) { - static_assert( - impl::position::pos != -1, - "Type not in static_variant." - ); - this->~static_variant(); + clean(); init(v); return *this; } static_variant& operator=( const static_variant& v ) { if( this == &v ) return *this; - this->~static_variant(); + clean(); v.visit( impl::copy_construct(*this) ); return *this; } static_variant& operator=( static_variant&& v ) { if( this == &v ) return *this; - this->~static_variant(); + clean(); v.visit( impl::move_construct(*this) ); return *this; } @@ -276,98 +286,73 @@ public: { return a.which() < b.which(); } - - template + template> X& get() { - static_assert( - impl::position::pos != -1, - "Type not in static_variant." - ); if(_tag == impl::position::pos) { - void* tmp(storage); - return *reinterpret_cast(tmp); + return *reinterpret_cast(storage.data()); } else { FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename::name()) ); - // std::string("static_variant does not contain value of type ") + typeid(X).name() - // ); } } - template + template> const X& get() const { - static_assert( - impl::position::pos != -1, - "Type not in static_variant." - ); if(_tag == impl::position::pos) { - const void* tmp(storage); - return *reinterpret_cast(tmp); + return *reinterpret_cast(storage.data()); } else { FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename::name()) ); } } template typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v); } - template typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v); } - template typename visitor::result_type visit(visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v); } - template typename visitor::result_type visit(const visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v); } - static int count() { return impl::type_info::count; } void set_which( int w ) { + FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); - this->~static_variant(); - _tag = w; - impl::storage_ops<0, Types...>::con(_tag, storage); + clean(); + init(w); } - int which() const {return _tag;} }; - template struct visitor { typedef Result result_type; }; - struct from_static_variant { variant& var; const uint32_t _max_depth; from_static_variant( variant& dv, uint32_t max_depth ):var(dv),_max_depth(max_depth){} - typedef void result_type; template void operator()( const T& v )const { to_variant( v, var, _max_depth ); } }; - struct to_static_variant { const variant& var; const uint32_t _max_depth; to_static_variant( const variant& dv, uint32_t max_depth ):var(dv),_max_depth(max_depth){} - typedef void result_type; template void operator()( T& v )const { from_variant( var, v, _max_depth ); } }; - - template void to_variant( const fc::static_variant& s, fc::variant& v, uint32_t max_depth ) { FC_ASSERT( max_depth > 0 ); @@ -384,6 +369,5 @@ struct visitor { s.set_which( ar[0].as_uint64() ); s.visit( to_static_variant(ar[1], max_depth - 1) ); } - template struct get_typename { static const char* name() { return typeid(static_variant).name(); } }; -} // namespace fc +} // namespace fc \ No newline at end of file diff --git a/src/static_variant.cpp b/src/static_variant.cpp new file mode 100644 index 0000000..63cbb8f --- /dev/null +++ b/src/static_variant.cpp @@ -0,0 +1,31 @@ +#include + + +namespace fc { namespace impl { + +dynamic_storage::dynamic_storage() : storage(nullptr) {}; + +dynamic_storage::~dynamic_storage() +{ + release(); +} + +void* dynamic_storage::data() const +{ + FC_ASSERT( storage != nullptr ); + return (void*)storage; +} + +void dynamic_storage::alloc( size_t size ) +{ + release(); + storage = new char[size]; +} + +void dynamic_storage::release() +{ + delete [] storage; + storage = nullptr; +} + +}}