From d0803ec9cdbdcd6a84b9d21bd67542941afd39ae Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 2 Mar 2015 18:24:37 -0500 Subject: [PATCH] Fixes circa safe and static_variant --- include/fc/safe.hpp | 3 +- include/fc/static_variant.hpp | 69 ++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp index ec46063..538f550 100644 --- a/include/fc/safe.hpp +++ b/include/fc/safe.hpp @@ -31,7 +31,8 @@ namespace fc { if( b.value < 0 && a.value < std::numeric_limits::min() - b.value ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) ); 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 { diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 122eee0..01c132f 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -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 * @@ -29,6 +29,7 @@ struct type_info; template struct copy_construct { + typedef void result_type; StaticVariant& sv; copy_construct( StaticVariant& s ):sv(s){} template @@ -38,11 +39,24 @@ struct copy_construct } }; +template +struct move_construct +{ + typedef void result_type; + StaticVariant& sv; + move_construct( StaticVariant& s ):sv(s){} + template + void operator()( T& v )const + { + 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) {} @@ -173,18 +187,26 @@ template class static_variant { 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 void init(const X& x) { _tag = impl::position::pos; new(storage) X(x); } + template + void init(X&& x) { + _tag = impl::position::pos; + new(storage) X( std::move(x) ); + } + template - friend struct copy_construct; + friend struct impl::copy_construct; + template + friend struct impl::move_construct; public: template struct tag @@ -204,7 +226,16 @@ public: template static_variant( const static_variant& cpy ) { - cpy.apply( impl::copy_construct>(*this) ); + cpy.visit( impl::copy_construct(*this) ); + } + static_variant( const static_variant& cpy ) + { + cpy.visit( impl::copy_construct(*this) ); + } + + static_variant( static_variant&& mv ) + { + mv.visit( impl::move_construct(*this) ); } template @@ -216,17 +247,35 @@ public: init(v); } ~static_variant() { - impl::storage_ops<0, Types...>::del(_tag, storage); + impl::storage_ops<0, Types...>::del(_tag, storage); } + + template - void operator=(const X& v) { + static_variant& operator=(const X& v) { static_assert( impl::position::pos != -1, "Type not in static_variant." ); this->~static_variant(); init(v); + return *this; } + static_variant& operator=( const static_variant& v ) + { + if( this == &v ) return *this; + this->~static_variant(); + v.visit( impl::copy_construct(*this) ); + return *this; + } + static_variant& operator=( static_variant&& v ) + { + if( this == &v ) return *this; + this->~static_variant(); + v.visit( impl::move_construct(*this) ); + return *this; + } + template X& get() { static_assert( @@ -274,8 +323,8 @@ public: typename visitor::result_type visit(const visitor& v)const { return impl::storage_ops<0, Types...>::apply(_tag, storage, v); } - - void set_which( int w ) { + + void set_which( int w ) { this->~static_variant(); impl::storage_ops<0, Types...>::con(_tag, storage); }