#ifndef _FC_OPTIONAL_HPP_ #define _FC_OPTIONAL_HPP_ #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. */ 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( 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( &u == &**this ) return *this; if( !_valid ) { new (&**this) T( fc::forward(u) ); _valid = true; } else { **this = fc::forward(u); } return *this; } optional& operator=( const optional& o ) { if( _valid && o._valid ) { **this = *o; } else if( !_valid && o._valid ) { *this = *o; } // else !_valid && !o._valid == same! return *this; } bool operator!()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; } } // namespace fc #endif