BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
optional.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <assert.h>
3 #include <utility>
4 
5 namespace fc {
6 #ifdef _MSC_VER
7 # pragma warning(push)
8 # pragma warning(disable:4521) /* multiple copy ctors */
9 # pragma warning(disable:4522) /* multiple assignment operators */
10 #endif
11  bool assert_optional(bool is_valid ); // defined in exception.cpp
12 
19  template<typename T>
20  class optional
21  {
22  public:
23  typedef T value_type;
24 
25  optional():_valid(false){}
26  ~optional(){ reset(); }
27 
29  :_valid(false)
30  {
31  if( o._valid ) new (ptr()) T( *o );
32  _valid = o._valid;
33  }
34 
35  optional( const optional& o )
36  :_valid(false)
37  {
38  if( o._valid ) new (ptr()) T( *o );
39  _valid = o._valid;
40  }
41 
43  :_valid(false)
44  {
45  if( o._valid ) new (ptr()) T( std::move(*o) );
46  _valid = o._valid;
47  o.reset();
48  }
49 
50  template<typename U>
51  optional( const optional<U>& o )
52  :_valid(false)
53  {
54  if( o._valid ) new (ptr()) T( *o );
55  _valid = o._valid;
56  }
57 
58  template<typename U>
60  :_valid(false)
61  {
62  if( o._valid )
63  {
64  new (ptr()) T( *o );
65  }
66  _valid = o._valid;
67  }
68 
69  template<typename U>
71  :_valid(false)
72  {
73  if( o._valid ) new (ptr()) T( std::move(*o) );
74  _valid = o._valid;
75  o.reset();
76  }
77 
78  template<typename U>
79  optional( U&& u )
80  :_valid(true)
81  {
82  new ((char*)ptr()) T( std::forward<U>(u) );
83  }
84 
85  template<typename U>
86  optional& operator=( U&& u )
87  {
88  reset();
89  new (ptr()) T( std::forward<U>(u) );
90  _valid = true;
91  return *this;
92  }
93 
94  template<typename U>
96  if (this != &o) {
97  if( _valid && o._valid ) {
98  ref() = *o;
99  } else if( !_valid && o._valid ) {
100  new (ptr()) T( *o );
101  _valid = true;
102  } else if (_valid) {
103  reset();
104  }
105  }
106  return *this;
107  }
108  template<typename U>
110  if (this != &o) {
111  if( _valid && o._valid ) {
112  ref() = *o;
113  } else if( !_valid && o._valid ) {
114  new (ptr()) T( *o );
115  _valid = true;
116  } else if (_valid) {
117  reset();
118  }
119  }
120  return *this;
121  }
122 
124  if (this != &o) {
125  if( _valid && o._valid ) {
126  ref() = *o;
127  } else if( !_valid && o._valid ) {
128  new (ptr()) T( *o );
129  _valid = true;
130  } else if (_valid) {
131  reset();
132  }
133  }
134  return *this;
135  }
136 
137  optional& operator=( const optional& o ) {
138  if (this != &o) {
139  if( _valid && o._valid ) {
140  ref() = *o;
141  } else if( !_valid && o._valid ) {
142  new (ptr()) T( *o );
143  _valid = true;
144  } else if (_valid) {
145  reset();
146  }
147  }
148  return *this;
149  }
150 
151  template<typename U>
153  {
154  if (this != &o)
155  {
156  if( _valid && o._valid )
157  {
158  ref() = std::move(*o);
159  o.reset();
160  } else if ( !_valid && o._valid ) {
161  *this = std::move(*o);
162  } else if (_valid) {
163  reset();
164  }
165  }
166  return *this;
167  }
168 
170  {
171  if (this != &o)
172  {
173  if( _valid && o._valid )
174  {
175  ref() = std::move(*o);
176  o.reset();
177  } else if ( !_valid && o._valid ) {
178  *this = std::move(*o);
179  } else if (_valid) {
180  reset();
181  }
182  }
183  return *this;
184  }
185 
186  bool valid()const { return _valid; }
187  bool operator!()const { return !_valid; }
188 
189  // this operation is not safe and can result in unintential
190  // casts and comparisons, use valid() or !!
191  explicit operator bool()const { return _valid; }
192 
193  T& operator*() { assert(_valid); return ref(); }
194  const T& operator*()const { assert(_valid); return ref(); }
195 
197  {
198  assert(_valid);
199  return ptr();
200  }
201  const T* operator->()const
202  {
203  assert(_valid);
204  return ptr();
205  }
206 
207  optional& operator=(std::nullptr_t)
208  {
209  reset();
210  return *this;
211  }
212 
213  friend bool operator < ( const optional a, optional b )
214  {
215  if( a.valid() && b.valid() ) return *a < *b;
216  return a.valid() < b.valid();
217  }
218  friend bool operator == ( const optional a, optional b )
219  {
220  if( a.valid() && b.valid() ) return *a == *b;
221  return a.valid() == b.valid();
222  }
223 
224  void reset()
225  {
226  if( _valid )
227  {
228  ref().~T(); // cal destructor
229  }
230  _valid = false;
231  }
232  private:
233  template<typename U> friend class optional;
234  T& ref() { return *ptr(); }
235  const T& ref()const { return *ptr(); }
236  T* ptr() { void* v = &_value[0]; return static_cast<T*>(v); }
237  const T* ptr()const { const void* v = &_value[0]; return static_cast<const T*>(v); }
238 
239  // force alignment... to 16 byte boundaries
240 #if defined(_MSC_VER)
241  double _value[((sizeof(T)+7)/8)] __declspec((align(16)));
242 #else
243  double _value[((sizeof(T)+7)/8)] __attribute__((aligned(16)));
244 #endif
245  bool _valid;
246  };
247 
248  template<typename T>
249  bool operator == ( const optional<T>& left, const optional<T>& right ) {
250  return (!left == !right) || (!!left && *left == *right);
251  }
252  template<typename T, typename U>
253  bool operator == ( const optional<T>& left, const U& u ) {
254  return !!left && *left == u;
255  }
256  template<typename T>
257  bool operator != ( const optional<T>& left, const optional<T>& right ) {
258  return (!left != !right) || (!!left && *left != *right);
259  }
260  template<typename T, typename U>
261  bool operator != ( const optional<T>& left, const U& u ) {
262  return !left || *left != u;
263  }
264 
265 #ifdef _MSC_VER
266 # pragma warning(pop)
267 #endif
268 
269 } // namespace fc
270 
fc::optional::operator->
const T * operator->() const
Definition: optional.hpp:201
fc::optional::reset
void reset()
Definition: optional.hpp:224
fc::assert_optional
bool assert_optional(bool is_valid)
Definition: exception.cpp:290
fc::optional::operator=
optional & operator=(optional &o)
Definition: optional.hpp:123
fc::optional::optional
optional(const optional< U > &o)
Definition: optional.hpp:51
fc
Definition: api.hpp:15
fc::optional::optional
optional(optional< U > &&o)
Definition: optional.hpp:70
fc::optional::operator*
T & operator*()
Definition: optional.hpp:193
fc::optional::value_type
T value_type
Definition: optional.hpp:23
fc::optional::optional
optional(optional &&o)
Definition: optional.hpp:42
fc::optional::operator=
optional & operator=(optional &&o)
Definition: optional.hpp:169
fc::optional::operator=
optional & operator=(const optional &o)
Definition: optional.hpp:137
fc::optional::valid
bool valid() const
Definition: optional.hpp:186
fc::optional::~optional
~optional()
Definition: optional.hpp:26
fc::optional::optional
optional(const optional &o)
Definition: optional.hpp:35
fc::optional::optional
optional(optional &o)
Definition: optional.hpp:28
fc::optional::operator=
optional & operator=(std::nullptr_t)
Definition: optional.hpp:207
fc::optional::operator<
friend bool operator<(const optional a, optional b)
Definition: optional.hpp:213
fc::optional::operator!
bool operator!() const
Definition: optional.hpp:187
fc::optional::operator=
optional & operator=(const optional< U > &o)
Definition: optional.hpp:109
fc::optional::operator=
optional & operator=(U &&u)
Definition: optional.hpp:86
fc::operator!=
bool operator!=(const optional< T > &left, const optional< T > &right)
Definition: optional.hpp:257
fc::optional::optional
optional()
Definition: optional.hpp:25
fc::optional::optional
optional(optional< U > &o)
Definition: optional.hpp:59
fc::optional::operator=
optional & operator=(optional< U > &o)
Definition: optional.hpp:95
fc::optional::optional
optional(U &&u)
Definition: optional.hpp:79
fc::optional::operator->
T * operator->()
Definition: optional.hpp:196
fc::optional
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
fc::optional::operator*
const T & operator*() const
Definition: optional.hpp:194
fc::operator==
bool operator==(const optional< T > &left, const optional< T > &right)
Definition: optional.hpp:249
fc::optional::operator=
optional & operator=(optional< U > &&o)
Definition: optional.hpp:152
fc::optional::operator==
friend bool operator==(const optional a, optional b)
Definition: optional.hpp:218