#pragma once #include namespace fc { /** * @brief provides stack-based nullable value similar to boost::optional * * Simply including boost::optional adds 35,000 lines to each object file, using * fc::optional adds less than 400. */ #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4521) /* multiple copy ctors */ #endif template class optional { public: optional():_valid(0){} ~optional(){ if( _valid ) (**this).~T(); } optional( const optional& o ) :_valid(false) { if( o._valid ) new (&**this) T( *o ); _valid = o._valid; } optional( optional& o ) :_valid(false) { if( o._valid ) new (&**this) T( *o ); _valid = o._valid; } optional( optional&& o ) :_valid(false) { if( o._valid ) new (&**this) T( fc::move(*o) ); _valid = o._valid; } template optional( U&& u ) :_valid(false) { new (&**this) T( fc::forward(u) ); _valid = true; } template optional& operator=( U&& u ) { if( !_valid ) { new (&**this) T( fc::forward(u) ); _valid = true; } else { **this = static_cast(fc::forward(u)); } return *this; } optional& operator=( const optional& o ) { if (this != &o) { if( _valid && o._valid ) { **this = *o; } else if( !_valid && o._valid ) { *this = *o; } else if (_valid) { (**this).~T(); _valid = false; } } return *this; } optional& operator=( optional&& o ) { if (this != &o) { if( _valid && o._valid ) { **this = fc::move(*o); } else if ( !_valid && o._valid ) { *this = fc::move(*o); } else if (_valid) { (**this).~T(); _valid = false; } } return *this; } bool operator!()const { return !_valid; } operator bool()const { return _valid; } T& operator*() { void* v = &_value[0]; return *static_cast(v); } const T& operator*()const { const void* v = &_value[0]; return *static_cast(v); } T* operator->() { void* v = &_value[0]; return static_cast(v); } const T* operator->()const { const void* v = &_value[0]; return static_cast(v); } private: // force alignment... to 8 byte boundaries double _value[8 * ((sizeof(T)+7)/8)]; bool _valid; }; template bool operator == ( const optional& left, const optional& right ) { return (!left == !right) || (!!left && *left == *right); } template bool operator == ( const optional& left, const U& u ) { return !!left && *left == u; } template bool operator != ( const optional& left, const optional& right ) { return (!left != !right) || (!!left && *left != *right); } template bool operator != ( const optional& left, const U& u ) { return !left || *left != u; } #ifdef _MSC_VER # pragma warning(pop) #endif } // namespace fc