$darkmode
optional.hpp
1 // Copyright satoren
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 
6 #pragma once
7 #include <cassert>
8 
9 namespace lrdb
10 {
13 
14  struct bad_optional_access :std::exception {};
15  struct nullopt_t {};
16 
18  template<class T>class optional
19  {
20  typedef void (optional::*bool_type)() const;
21  void this_type_does_not_support_comparisons() const {}
22  public:
23  optional() : value_(0) {};
24  optional(nullopt_t) : value_(0) {};
25  optional(const optional& other) : value_(0)
26  {
27  if (other)
28  {
29  value_ = new(&storage_) T(other.value());
30  }
31  }
32  optional(const T& value)
33  {
34  value_ = new(&storage_) T(value);
35  }
36 
37  ~optional() {
38  destruct();
39  }
40  optional& operator=(nullopt_t) { destruct(); return *this; }
41  optional& operator=(const optional& other)
42  {
43  if (other)
44  {
45  *this = other.value();
46  }
47  else
48  {
49  destruct();
50  }
51  return *this;
52  }
53  optional& operator=(const T& value)
54  {
55  if (value_)
56  {
57  *value_ = value;
58  }
59  else
60  {
61  value_ = new(&storage_) T(value);
62  }
63  return *this;
64  }
65 
66 #if KAGUYA_USE_CPP11
67  optional(optional&& other) :value_(0)
68  {
69  if (other)
70  {
71  value_ = new(&storage_) T(std::move(other.value()));
72  }
73  }
74  optional(T&& value)
75  {
76  value_ = new(&storage_) T(std::move(value));
77  }
78  optional& operator=(optional&& other)
79  {
80  if (other)
81  {
82  *this = std::move(other.value());
83  }
84  else
85  {
86  destruct();
87  }
88  return *this;
89  }
90  optional& operator=(T&& value)
91  {
92  if (value_)
93  {
94  *value_ = std::move(value);
95  }
96  else
97  {
98  value_ = new(&storage_) T(std::move(value));
99  }
100  return *this;
101  }
102 #endif
103 
104  operator bool_type() const
105  {
106  this_type_does_not_support_comparisons();
107  return value_ != 0 ? &optional::this_type_does_not_support_comparisons : 0;
108  }
109  T& value()
110  {
111  if (value_) { return *value_; }
112  throw bad_optional_access();
113  }
114  const T & value() const
115  {
116  if (value_) { return *value_; }
117  throw bad_optional_access();
118  }
119 
120 #if KAGUYA_USE_CPP11
121  template< class U >
122  T value_or(U&& default_value) const
123  {
124  if (value_) { return *value_; }
125  return default_value;
126  }
127 #else
128  template< class U >
129  T value_or(const U& default_value)const
130  {
131  if (value_) { return *value_; }
132  return default_value;
133  }
134 #endif
135  const T* operator->() const { assert(value_); return value_; }
136  T* operator->() { assert(value_); return value_; }
137  const T& operator*() const { assert(value_); return *value_; }
138  T& operator*() { assert(value_); return *value_; }
139  private:
140  void destruct()
141  {
142  if (value_)
143  {
144  value_->~T(); value_ = 0;
145  }
146  }
147 
148  typename std::aligned_storage<sizeof(T),
149  std::alignment_of<T>::value>::type storage_;
150 
151  T* value_;
152  };
153 
156  template<class T>class optional<T&>
157  {
158  typedef void (optional::*bool_type)() const;
159  void this_type_does_not_support_comparisons() const {}
160  public:
161  optional() : value_(0) {};
162  optional(nullopt_t) : value_(0) {};
163 
164  optional(const optional& other) :value_(other.value_) { }
165  optional(T& value) :value_(&value) { }
166 
167  ~optional() {
168  }
169  optional& operator=(nullopt_t) {
170  value_ = 0;
171  return *this;
172  }
173  optional& operator=(const optional& other)
174  {
175  value_ = other.value_;
176  return *this;
177  }
178  optional& operator=(T& value)
179  {
180  value_ = &value;
181  return *this;
182  }
183  operator bool_type() const
184  {
185  this_type_does_not_support_comparisons();
186  return value_ != 0 ? &optional::this_type_does_not_support_comparisons : 0;
187  }
188  T& value()
189  {
190  if (value_) { return *value_; }
191  throw bad_optional_access();
192  }
193  const T & value() const
194  {
195  if (value_) { return *value_; }
196  throw bad_optional_access();
197  }
198 
199 #if KAGUYA_USE_CPP11
200  T& value_or(T& default_value) const
201  {
202  if (value_) { return *value_; }
203  return default_value;
204  }
205 #else
206  T& value_or(T& default_value)const
207  {
208  if (value_) { return *value_; }
209  return default_value;
210  }
211 #endif
212 
213  const T* operator->() const { assert(value_); return value_; }
214  T* operator->() { assert(value_); return value_; }
215  const T& operator*() const { assert(value_); return *value_; }
216  T& operator*() { assert(value_); return *value_; }
217  private:
218  T* value_;
219  };
220 
224  template< class T >
225  bool operator==(const optional<T>& lhs, const optional<T>& rhs)
226  {
227  if (bool(lhs) != bool(rhs)) { return false; }
228  if (bool(lhs) == false) { return true; }
229  return lhs.value() == rhs.value();
230  }
231  template< class T >
232  bool operator!=(const optional<T>& lhs, const optional<T>& rhs)
233  {
234  return !(lhs == rhs);
235  }
236  template< class T >
237  bool operator<(const optional<T>& lhs, const optional<T>& rhs)
238  {
239  if (!bool(rhs)) { return false; }
240  if (!bool(lhs)) { return true; }
241  return lhs.value() < rhs.value();
242  }
243  template< class T >
244  bool operator<=(const optional<T>& lhs, const optional<T>& rhs)
245  {
246  return !(rhs < lhs);
247  }
248  template< class T >
249  bool operator>(const optional<T>& lhs, const optional<T>& rhs)
250  {
251  return rhs < lhs;
252  }
253  template< class T >
254  bool operator>=(const optional<T>& lhs, const optional<T>& rhs)
255  {
256  return !(lhs < rhs);
257  }
259 
261 }
self implement for std::optional(C++17 feature).
Definition: optional.hpp:19
Definition: optional.hpp:14
Definition: optional.hpp:15