Dynamic memory allocation of static_variant & other small changes.
This commit is contained in:
parent
acfe075c5d
commit
93a0316607
3 changed files with 115 additions and 51 deletions
|
|
@ -210,6 +210,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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/** 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
|
||||
*
|
||||
|
|
@ -176,6 +176,41 @@ struct type_info<> {
|
|||
static const size_t size = 0;
|
||||
};
|
||||
|
||||
template<typename TTag>
|
||||
size_t size( TTag )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename TTag, typename A, typename...Ts>
|
||||
size_t size( TTag tag )
|
||||
{
|
||||
if (tag <= 0)
|
||||
{
|
||||
return sizeof(A);
|
||||
}
|
||||
|
||||
return size<TTag, Ts...>( --tag );
|
||||
}
|
||||
|
||||
|
||||
class dynamic_storage
|
||||
{
|
||||
char* storage;
|
||||
public:
|
||||
dynamic_storage();
|
||||
|
||||
~dynamic_storage();
|
||||
|
||||
void* data() const;
|
||||
|
||||
void alloc( size_t size );
|
||||
|
||||
void release();
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template<typename Visitor,typename Data>
|
||||
|
|
@ -213,40 +248,57 @@ class static_variant {
|
|||
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
|
||||
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
|
||||
|
||||
template<typename X>
|
||||
using type_in_typelist = typename std::enable_if<impl::position<X, Types...>::pos != -1, X>::type; // type is in typelist of static_variant.
|
||||
|
||||
using tag_type = int64_t;
|
||||
tag_type _tag;
|
||||
char storage[impl::type_info<Types...>::size];
|
||||
impl::dynamic_storage storage;
|
||||
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
void init(const X& x) {
|
||||
_tag = impl::position<X, Types...>::pos;
|
||||
new(storage) X(x);
|
||||
storage.alloc( sizeof(X) );
|
||||
new(storage.data()) X(x);
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
void init(X&& x) {
|
||||
_tag = impl::position<X, Types...>::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_type, Types...>( tag ) );
|
||||
impl::storage_ops<0, Types...>::con(_tag, storage.data());
|
||||
}
|
||||
|
||||
void clean()
|
||||
{
|
||||
impl::storage_ops<0, Types...>::del(_tag, storage.data() );
|
||||
storage.release();
|
||||
}
|
||||
|
||||
|
||||
template<typename StaticVariant>
|
||||
friend struct impl::copy_construct;
|
||||
template<typename StaticVariant>
|
||||
friend struct impl::move_construct;
|
||||
public:
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
struct tag
|
||||
{
|
||||
static_assert(
|
||||
impl::position<X, Types...>::pos != -1,
|
||||
"Type not in static_variant."
|
||||
);
|
||||
static const int value = impl::position<X, Types...>::pos;
|
||||
};
|
||||
|
||||
static_variant()
|
||||
{
|
||||
_tag = 0;
|
||||
impl::storage_ops<0, Types...>::con(0, storage);
|
||||
init(0);
|
||||
}
|
||||
|
||||
template<typename... Other>
|
||||
|
|
@ -254,6 +306,7 @@ public:
|
|||
{
|
||||
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||
}
|
||||
|
||||
static_variant( const static_variant& cpy )
|
||||
{
|
||||
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||
|
|
@ -264,40 +317,32 @@ public:
|
|||
mv.visit( impl::move_construct<static_variant>(*this) );
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
static_variant(const X& v) {
|
||||
static_assert(
|
||||
impl::position<X, Types...>::pos != -1,
|
||||
"Type not in static_variant."
|
||||
);
|
||||
init(v);
|
||||
}
|
||||
|
||||
~static_variant() {
|
||||
impl::storage_ops<0, Types...>::del(_tag, storage);
|
||||
clean();
|
||||
}
|
||||
|
||||
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
static_variant& operator=(const X& v) {
|
||||
static_assert(
|
||||
impl::position<X, Types...>::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<static_variant>(*this) );
|
||||
return *this;
|
||||
}
|
||||
static_variant& operator=( static_variant&& v )
|
||||
{
|
||||
if( this == &v ) return *this;
|
||||
this->~static_variant();
|
||||
clean();
|
||||
v.visit( impl::move_construct<static_variant>(*this) );
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -310,52 +355,40 @@ public:
|
|||
return a.which() < b.which();
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
X& get() {
|
||||
static_assert(
|
||||
impl::position<X, Types...>::pos != -1,
|
||||
"Type not in static_variant."
|
||||
);
|
||||
if(_tag == impl::position<X, Types...>::pos) {
|
||||
void* tmp(storage);
|
||||
return *reinterpret_cast<X*>(tmp);
|
||||
return *reinterpret_cast<X*>(storage.data());
|
||||
} else {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
|
||||
// std::string("static_variant does not contain value of type ") + typeid(X).name()
|
||||
// );
|
||||
}
|
||||
}
|
||||
template<typename X>
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
const X& get() const {
|
||||
static_assert(
|
||||
impl::position<X, Types...>::pos != -1,
|
||||
"Type not in static_variant."
|
||||
);
|
||||
if(_tag == impl::position<X, Types...>::pos) {
|
||||
const void* tmp(storage);
|
||||
return *reinterpret_cast<const X*>(tmp);
|
||||
return *reinterpret_cast<const X*>(storage.data());
|
||||
} else {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
|
||||
}
|
||||
}
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(visitor& v) {
|
||||
return visit( _tag, v, (void*) storage );
|
||||
return visit( _tag, v, (void*) storage.data() );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(const visitor& v) {
|
||||
return visit( _tag, v, (void*) storage );
|
||||
return visit( _tag, v, (void*) storage.data() );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(visitor& v)const {
|
||||
return visit( _tag, v, (const void*) storage );
|
||||
return visit( _tag, v, (const void*) storage.data() );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(const visitor& v)const {
|
||||
return visit( _tag, v, (const void*) storage );
|
||||
return visit( _tag, v, (const void*) storage.data() );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
|
|
@ -394,9 +427,8 @@ public:
|
|||
void set_which( tag_type 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);
|
||||
}
|
||||
|
||||
tag_type which() const {return _tag;}
|
||||
|
|
|
|||
31
src/static_variant.cpp
Normal file
31
src/static_variant.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <fc/static_variant.hpp>
|
||||
|
||||
|
||||
namespace fc { namespace impl {
|
||||
|
||||
dynamic_storage::dynamic_storage() : storage(nullptr) {};
|
||||
|
||||
dynamic_storage::~dynamic_storage()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
void* dynamic_storage::data() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
Loading…
Reference in a new issue