2013-02-04 16:13:02 +00:00
|
|
|
#pragma once
|
2012-09-08 02:50:37 +00:00
|
|
|
#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.
|
|
|
|
|
*/
|
2013-06-05 19:19:00 +00:00
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
# pragma warning(push)
|
|
|
|
|
# pragma warning(disable:4521) /* multiple copy ctors */
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 19:19:00 +00:00
|
|
|
optional( optional& o )
|
|
|
|
|
:_valid(false) {
|
|
|
|
|
if( o._valid ) new (&**this) T( *o );
|
|
|
|
|
_valid = o._valid;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
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 {
|
2013-06-05 19:19:00 +00:00
|
|
|
**this = static_cast<T>(fc::forward<U>(u));
|
2012-09-08 02:50:37 +00:00
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optional& operator=( const optional& o ) {
|
2013-06-05 19:19:00 +00:00
|
|
|
if (this != &o) {
|
|
|
|
|
if( _valid && o._valid ) {
|
|
|
|
|
**this = *o;
|
|
|
|
|
} else if( !_valid && o._valid ) {
|
|
|
|
|
*this = *o;
|
|
|
|
|
} else if (_valid) {
|
|
|
|
|
(**this).~T();
|
|
|
|
|
_valid = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-09-08 02:50:37 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
2013-06-05 19:19:00 +00:00
|
|
|
|
2012-11-16 17:40:28 +00:00
|
|
|
optional& operator=( optional&& o ) {
|
2013-06-05 19:19:00 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-16 17:40:28 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 19:19:00 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
# pragma warning(pop)
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
} // namespace fc
|
|
|
|
|
|