Fixes circa safe and static_variant
This commit is contained in:
parent
b393ddc1da
commit
d0803ec9cd
2 changed files with 61 additions and 11 deletions
|
|
@ -31,7 +31,8 @@ namespace fc {
|
||||||
if( b.value < 0 && a.value < std::numeric_limits<T>::min() - b.value ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
if( b.value < 0 && a.value < std::numeric_limits<T>::min() - b.value ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||||
return safe(a.value+b.value);
|
return safe(a.value+b.value);
|
||||||
}
|
}
|
||||||
safe& operator *= ( T v ) { value *= v; return *this; }
|
safe& operator *= ( safe v ) { value *= v.value; return *this; }
|
||||||
|
safe& operator /= ( safe v ) { FC_ASSERT(v.value != 0); value /= v.value; return *this; }
|
||||||
safe& operator -= ( const safe& b ) { return *this += safe(-b.value); }
|
safe& operator -= ( const safe& b ) { return *this += safe(-b.value); }
|
||||||
safe operator -()const
|
safe operator -()const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 Kenneth Micklas
|
* Copyright (C) 2013 Kenneth Micklas
|
||||||
*
|
*
|
||||||
|
|
@ -29,6 +29,7 @@ struct type_info;
|
||||||
template<typename StaticVariant>
|
template<typename StaticVariant>
|
||||||
struct copy_construct
|
struct copy_construct
|
||||||
{
|
{
|
||||||
|
typedef void result_type;
|
||||||
StaticVariant& sv;
|
StaticVariant& sv;
|
||||||
copy_construct( StaticVariant& s ):sv(s){}
|
copy_construct( StaticVariant& s ):sv(s){}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -38,11 +39,24 @@ struct copy_construct
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename StaticVariant>
|
||||||
|
struct move_construct
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
StaticVariant& sv;
|
||||||
|
move_construct( StaticVariant& s ):sv(s){}
|
||||||
|
template<typename T>
|
||||||
|
void operator()( T& v )const
|
||||||
|
{
|
||||||
|
sv.init( std::move(v) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<int N, typename T, typename... Ts>
|
template<int N, typename T, typename... Ts>
|
||||||
struct storage_ops<N, T&, Ts...> {
|
struct storage_ops<N, T&, Ts...> {
|
||||||
static void del(int n, void *data) {}
|
static void del(int n, void *data) {}
|
||||||
static void con(int n, void *data) {}
|
static void con(int n, void *data) {}
|
||||||
|
|
||||||
template<typename visitor>
|
template<typename visitor>
|
||||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
|
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
|
||||||
|
|
||||||
|
|
@ -173,18 +187,26 @@ template<typename... Types>
|
||||||
class static_variant {
|
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_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.");
|
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
|
||||||
|
|
||||||
int _tag;
|
int _tag;
|
||||||
char storage[impl::type_info<Types...>::size];
|
char storage[impl::type_info<Types...>::size];
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
void init(const X& x) {
|
void init(const X& x) {
|
||||||
_tag = impl::position<X, Types...>::pos;
|
_tag = impl::position<X, Types...>::pos;
|
||||||
new(storage) X(x);
|
new(storage) X(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename X>
|
||||||
|
void init(X&& x) {
|
||||||
|
_tag = impl::position<X, Types...>::pos;
|
||||||
|
new(storage) X( std::move(x) );
|
||||||
|
}
|
||||||
|
|
||||||
template<typename StaticVariant>
|
template<typename StaticVariant>
|
||||||
friend struct copy_construct;
|
friend struct impl::copy_construct;
|
||||||
|
template<typename StaticVariant>
|
||||||
|
friend struct impl::move_construct;
|
||||||
public:
|
public:
|
||||||
template<typename X>
|
template<typename X>
|
||||||
struct tag
|
struct tag
|
||||||
|
|
@ -204,7 +226,16 @@ public:
|
||||||
template<typename... Other>
|
template<typename... Other>
|
||||||
static_variant( const static_variant<Other...>& cpy )
|
static_variant( const static_variant<Other...>& cpy )
|
||||||
{
|
{
|
||||||
cpy.apply( impl::copy_construct<static_variant<Types...>>(*this) );
|
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||||
|
}
|
||||||
|
static_variant( const static_variant& cpy )
|
||||||
|
{
|
||||||
|
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static_variant( static_variant&& mv )
|
||||||
|
{
|
||||||
|
mv.visit( impl::move_construct<static_variant>(*this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
|
|
@ -216,17 +247,35 @@ public:
|
||||||
init(v);
|
init(v);
|
||||||
}
|
}
|
||||||
~static_variant() {
|
~static_variant() {
|
||||||
impl::storage_ops<0, Types...>::del(_tag, storage);
|
impl::storage_ops<0, Types...>::del(_tag, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
void operator=(const X& v) {
|
static_variant& operator=(const X& v) {
|
||||||
static_assert(
|
static_assert(
|
||||||
impl::position<X, Types...>::pos != -1,
|
impl::position<X, Types...>::pos != -1,
|
||||||
"Type not in static_variant."
|
"Type not in static_variant."
|
||||||
);
|
);
|
||||||
this->~static_variant();
|
this->~static_variant();
|
||||||
init(v);
|
init(v);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
static_variant& operator=( const static_variant& v )
|
||||||
|
{
|
||||||
|
if( this == &v ) return *this;
|
||||||
|
this->~static_variant();
|
||||||
|
v.visit( impl::copy_construct<static_variant>(*this) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
static_variant& operator=( static_variant&& v )
|
||||||
|
{
|
||||||
|
if( this == &v ) return *this;
|
||||||
|
this->~static_variant();
|
||||||
|
v.visit( impl::move_construct<static_variant>(*this) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename X>
|
template<typename X>
|
||||||
X& get() {
|
X& get() {
|
||||||
static_assert(
|
static_assert(
|
||||||
|
|
@ -274,8 +323,8 @@ public:
|
||||||
typename visitor::result_type visit(const visitor& v)const {
|
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, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_which( int w ) {
|
void set_which( int w ) {
|
||||||
this->~static_variant();
|
this->~static_variant();
|
||||||
impl::storage_ops<0, Types...>::con(_tag, storage);
|
impl::storage_ops<0, Types...>::con(_tag, storage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue