2013-02-04 16:13:02 +00:00
|
|
|
#pragma once
|
2012-09-08 02:50:37 +00:00
|
|
|
#include <fc/utility.hpp>
|
2013-07-02 18:59:05 +00:00
|
|
|
#include <assert.h>
|
2020-10-29 18:47:49 +00:00
|
|
|
#include <string.h>
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2013-07-05 23:48:59 +00:00
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
namespace fc {
|
2013-07-02 18:59:05 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
# pragma warning(push)
|
|
|
|
|
# pragma warning(disable:4521) /* multiple copy ctors */
|
2013-10-11 02:19:01 +00:00
|
|
|
# pragma warning(disable:4522) /* multiple assignment operators */
|
2013-07-02 18:59:05 +00:00
|
|
|
#endif
|
2014-06-12 01:46:26 +00:00
|
|
|
bool assert_optional(bool is_valid ); // defined in exception.cpp
|
2013-07-02 18:59:05 +00:00
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
/**
|
|
|
|
|
* @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>
|
2016-02-26 19:22:11 +00:00
|
|
|
class optional
|
2013-07-02 18:59:05 +00:00
|
|
|
{
|
2012-09-08 02:50:37 +00:00
|
|
|
public:
|
2016-02-26 19:22:11 +00:00
|
|
|
typedef T value_type;
|
|
|
|
|
|
2020-10-29 18:47:49 +00:00
|
|
|
optional():_valid(false){ memset(_value, 0, sizeof(_value)); }
|
2013-07-02 18:59:05 +00:00
|
|
|
~optional(){ reset(); }
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2013-08-19 03:41:53 +00:00
|
|
|
optional( optional& o )
|
2013-07-02 18:59:05 +00:00
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-07-02 18:59:05 +00:00
|
|
|
if( o._valid ) new (ptr()) T( *o );
|
2012-09-08 02:50:37 +00:00
|
|
|
_valid = o._valid;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-19 03:41:53 +00:00
|
|
|
optional( const optional& o )
|
2013-07-02 18:59:05 +00:00
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-07-02 18:59:05 +00:00
|
|
|
if( o._valid ) new (ptr()) T( *o );
|
2013-06-05 19:19:00 +00:00
|
|
|
_valid = o._valid;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
optional( optional&& o )
|
2013-07-02 18:59:05 +00:00
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-07-02 18:59:05 +00:00
|
|
|
if( o._valid ) new (ptr()) T( fc::move(*o) );
|
2012-09-08 02:50:37 +00:00
|
|
|
_valid = o._valid;
|
2013-07-02 18:59:05 +00:00
|
|
|
o.reset();
|
2012-09-08 02:50:37 +00:00
|
|
|
}
|
|
|
|
|
|
2013-08-19 03:41:53 +00:00
|
|
|
template<typename U>
|
|
|
|
|
optional( const optional<U>& o )
|
|
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-08-19 03:41:53 +00:00
|
|
|
if( o._valid ) new (ptr()) T( *o );
|
|
|
|
|
_valid = o._valid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
|
optional( optional<U>& o )
|
|
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-08-19 03:41:53 +00:00
|
|
|
if( o._valid )
|
|
|
|
|
{
|
|
|
|
|
new (ptr()) T( *o );
|
|
|
|
|
}
|
|
|
|
|
_valid = o._valid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
|
optional( optional<U>&& o )
|
|
|
|
|
:_valid(false)
|
|
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-08-19 03:41:53 +00:00
|
|
|
if( o._valid ) new (ptr()) T( fc::move(*o) );
|
|
|
|
|
_valid = o._valid;
|
|
|
|
|
o.reset();
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
template<typename U>
|
|
|
|
|
optional( U&& u )
|
2013-07-05 23:48:59 +00:00
|
|
|
:_valid(true)
|
2013-07-02 18:59:05 +00:00
|
|
|
{
|
2020-10-29 18:47:49 +00:00
|
|
|
memset(_value, 0, sizeof(_value));
|
2013-07-05 23:48:59 +00:00
|
|
|
new ((char*)ptr()) T( fc::forward<U>(u) );
|
2012-09-08 02:50:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename U>
|
2013-07-02 18:59:05 +00:00
|
|
|
optional& operator=( U&& u )
|
|
|
|
|
{
|
|
|
|
|
reset();
|
|
|
|
|
new (ptr()) T( fc::forward<U>(u) );
|
2013-07-05 23:48:59 +00:00
|
|
|
_valid = true;
|
2012-09-08 02:50:37 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-19 03:41:53 +00:00
|
|
|
template<typename U>
|
|
|
|
|
optional& operator=( optional<U>& o ) {
|
|
|
|
|
if (this != &o) {
|
|
|
|
|
if( _valid && o._valid ) {
|
|
|
|
|
ref() = *o;
|
|
|
|
|
} else if( !_valid && o._valid ) {
|
|
|
|
|
new (ptr()) T( *o );
|
|
|
|
|
_valid = true;
|
|
|
|
|
} else if (_valid) {
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
template<typename U>
|
|
|
|
|
optional& operator=( const optional<U>& o ) {
|
|
|
|
|
if (this != &o) {
|
|
|
|
|
if( _valid && o._valid ) {
|
|
|
|
|
ref() = *o;
|
|
|
|
|
} else if( !_valid && o._valid ) {
|
|
|
|
|
new (ptr()) T( *o );
|
|
|
|
|
_valid = true;
|
|
|
|
|
} else if (_valid) {
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optional& operator=( optional& o ) {
|
|
|
|
|
if (this != &o) {
|
|
|
|
|
if( _valid && o._valid ) {
|
|
|
|
|
ref() = *o;
|
|
|
|
|
} else if( !_valid && o._valid ) {
|
|
|
|
|
new (ptr()) T( *o );
|
|
|
|
|
_valid = true;
|
|
|
|
|
} else if (_valid) {
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
optional& operator=( const optional& o ) {
|
2013-06-05 19:19:00 +00:00
|
|
|
if (this != &o) {
|
|
|
|
|
if( _valid && o._valid ) {
|
2013-07-02 18:59:05 +00:00
|
|
|
ref() = *o;
|
2013-06-05 19:19:00 +00:00
|
|
|
} else if( !_valid && o._valid ) {
|
2013-07-02 18:59:05 +00:00
|
|
|
new (ptr()) T( *o );
|
|
|
|
|
_valid = true;
|
2013-06-05 19:19:00 +00:00
|
|
|
} else if (_valid) {
|
2013-07-02 18:59:05 +00:00
|
|
|
reset();
|
2013-06-05 19:19:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-09-08 02:50:37 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
2013-06-05 19:19:00 +00:00
|
|
|
|
2013-08-19 03:41:53 +00:00
|
|
|
template<typename U>
|
|
|
|
|
optional& operator=( optional<U>&& o )
|
|
|
|
|
{
|
|
|
|
|
if (this != &o)
|
|
|
|
|
{
|
|
|
|
|
if( _valid && o._valid )
|
|
|
|
|
{
|
|
|
|
|
ref() = fc::move(*o);
|
|
|
|
|
o.reset();
|
|
|
|
|
} else if ( !_valid && o._valid ) {
|
|
|
|
|
*this = fc::move(*o);
|
|
|
|
|
} else if (_valid) {
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-02 18:59:05 +00:00
|
|
|
optional& operator=( optional&& o )
|
|
|
|
|
{
|
|
|
|
|
if (this != &o)
|
|
|
|
|
{
|
2013-07-05 23:48:59 +00:00
|
|
|
if( _valid && o._valid )
|
|
|
|
|
{
|
2013-07-02 18:59:05 +00:00
|
|
|
ref() = fc::move(*o);
|
2013-07-05 23:48:59 +00:00
|
|
|
o.reset();
|
2013-06-05 19:19:00 +00:00
|
|
|
} else if ( !_valid && o._valid ) {
|
|
|
|
|
*this = fc::move(*o);
|
|
|
|
|
} else if (_valid) {
|
2013-07-02 18:59:05 +00:00
|
|
|
reset();
|
2013-06-05 19:19:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-11-16 17:40:28 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2013-08-19 02:44:48 +00:00
|
|
|
bool valid()const { return _valid; }
|
2012-09-08 02:50:37 +00:00
|
|
|
bool operator!()const { return !_valid; }
|
2014-05-20 15:25:31 +00:00
|
|
|
|
|
|
|
|
// this operation is not safe and can result in unintential
|
|
|
|
|
// casts and comparisons, use valid() or !!
|
|
|
|
|
explicit operator bool()const { return _valid; }
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2014-08-28 15:42:46 +00:00
|
|
|
T& operator*() { assert(_valid); return ref(); }
|
|
|
|
|
const T& operator*()const { assert(_valid); return ref(); }
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2013-07-02 18:59:05 +00:00
|
|
|
T* operator->()
|
|
|
|
|
{
|
2014-08-28 15:42:46 +00:00
|
|
|
assert(_valid);
|
2013-07-02 18:59:05 +00:00
|
|
|
return ptr();
|
|
|
|
|
}
|
|
|
|
|
const T* operator->()const
|
|
|
|
|
{
|
2014-08-28 15:42:46 +00:00
|
|
|
assert(_valid);
|
2013-07-02 18:59:05 +00:00
|
|
|
return ptr();
|
|
|
|
|
}
|
2012-09-08 02:50:37 +00:00
|
|
|
|
2013-07-10 01:06:23 +00:00
|
|
|
optional& operator=(std::nullptr_t)
|
|
|
|
|
{
|
|
|
|
|
reset();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-29 22:01:17 +00:00
|
|
|
friend bool operator < ( const optional a, optional b )
|
|
|
|
|
{
|
|
|
|
|
if( a.valid() && b.valid() ) return *a < *b;
|
|
|
|
|
return a.valid() < b.valid();
|
|
|
|
|
}
|
|
|
|
|
friend bool operator == ( const optional a, optional b )
|
|
|
|
|
{
|
|
|
|
|
if( a.valid() && b.valid() ) return *a == *b;
|
|
|
|
|
return a.valid() == b.valid();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-02 18:59:05 +00:00
|
|
|
void reset()
|
|
|
|
|
{
|
|
|
|
|
if( _valid )
|
|
|
|
|
{
|
|
|
|
|
ref().~T(); // cal destructor
|
|
|
|
|
}
|
2013-07-05 23:48:59 +00:00
|
|
|
_valid = false;
|
2013-07-02 18:59:05 +00:00
|
|
|
}
|
2013-07-10 01:06:23 +00:00
|
|
|
private:
|
2013-08-19 05:46:28 +00:00
|
|
|
template<typename U> friend class optional;
|
2013-07-02 18:59:05 +00:00
|
|
|
T& ref() { return *ptr(); }
|
|
|
|
|
const T& ref()const { return *ptr(); }
|
|
|
|
|
T* ptr() { void* v = &_value[0]; return static_cast<T*>(v); }
|
|
|
|
|
const T* ptr()const { const void* v = &_value[0]; return static_cast<const T*>(v); }
|
|
|
|
|
|
2012-09-08 02:50:37 +00:00
|
|
|
// force alignment... to 8 byte boundaries
|
2015-07-09 17:39:20 +00:00
|
|
|
double _value[((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
|
|
|
|
|
|