2012-09-08 02:50:37 +00:00
|
|
|
#ifndef _FC_OPTIONAL_HPP_
|
|
|
|
|
#define _FC_OPTIONAL_HPP_
|
|
|
|
|
#include <fc/utility.hpp>
|
|
|
|
|
|
|
|
|
|
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<typename T>
|
|
|
|
|
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<typename U>
|
|
|
|
|
optional( U&& u )
|
|
|
|
|
:_valid(false) {
|
|
|
|
|
new (&**this) T( fc::forward<U>(u) );
|
|
|
|
|
_valid = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
|
optional& operator=( U&& u ) {
|
|
|
|
|
if( !_valid ) {
|
|
|
|
|
new (&**this) T( fc::forward<U>(u) );
|
|
|
|
|
_valid = true;
|
|
|
|
|
} else {
|
2012-09-25 21:45:28 +00:00
|
|
|
**this = fc::forward<U>(u);
|
2012-09-08 02:50:37 +00:00
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optional& operator=( const optional& o ) {
|
2012-09-25 21:45:28 +00:00
|
|
|
if( _valid && o._valid ) { **this = *o; }
|
2012-09-08 02:50:37 +00:00
|
|
|
else if( !_valid && o._valid ) {
|
2012-09-25 21:45:28 +00:00
|
|
|
*this = *o;
|
2012-09-08 02:50:37 +00:00
|
|
|
} // else !_valid && !o._valid == same!
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2012-11-16 17:40:28 +00:00
|
|
|
optional& operator=( optional&& o ) {
|
|
|
|
|
if( _valid && o._valid ) { **this = fc::move(*o); }
|
|
|
|
|
else if( !_valid && o._valid ) {
|
|
|
|
|
*this = fc::move(*o);
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2012-09-08 02:50:37 +00:00
|
|
|
|
|
|
|
|
bool operator!()const { return !_valid; }
|
2012-11-16 17:40:28 +00:00
|
|
|
operator bool()const { return _valid; }
|
2012-09-08 02:50:37 +00:00
|
|
|
|
|
|
|
|
T& operator*() { void* v = &_value[0]; return *static_cast<T*>(v); }
|
|
|
|
|
const T& operator*()const { const void* v = &_value[0]; return *static_cast<const T*>(v); }
|
|
|
|
|
|
2012-09-25 21:45:28 +00:00
|
|
|
T* operator->() { void* v = &_value[0]; return static_cast<T*>(v); }
|
|
|
|
|
const T* operator->()const { const void* v = &_value[0]; return static_cast<const T*>(v); }
|
2012-09-08 02:50:37 +00:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// force alignment... to 8 byte boundaries
|
2012-09-15 02:47:37 +00:00
|
|
|
double _value[8 * ((sizeof(T)+7)/8)];
|
2012-09-08 02:50:37 +00:00
|
|
|
bool _valid;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool operator == ( const optional<T>& left, const optional<T>& right ) {
|
|
|
|
|
return (!left == !right) || (!!left && *left == *right);
|
|
|
|
|
}
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
|
bool operator == ( const optional<T>& left, const U& u ) {
|
|
|
|
|
return !!left && *left == u;
|
|
|
|
|
}
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool operator != ( const optional<T>& left, const optional<T>& right ) {
|
|
|
|
|
return (!left != !right) || (!!left && *left != *right);
|
|
|
|
|
}
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
|
bool operator != ( const optional<T>& left, const U& u ) {
|
|
|
|
|
return !left || *left != u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace fc
|
|
|
|
|
|
|
|
|
|
#endif
|