1 | // Copyright (C) 2011 - 2012 Andrzej Krzemienski. |
2 | // |
3 | // Use, modification, and distribution is subject to the Boost Software |
4 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // The idea and interface is based on Boost.Optional library |
8 | // authored by Fernando Luis Cacciola Carballal |
9 | |
10 | # ifndef ___OPTIONAL_HPP___ |
11 | # define ___OPTIONAL_HPP___ |
12 | |
13 | # include <utility> |
14 | # include <type_traits> |
15 | # include <initializer_list> |
16 | # include <cassert> |
17 | # include <functional> |
18 | # include <string> |
19 | # include <stdexcept> |
20 | |
21 | # define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false |
22 | |
23 | # if defined __GNUC__ // NOTE: GNUC is also defined for Clang |
24 | # if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) |
25 | # define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ |
26 | # elif (__GNUC__ > 4) |
27 | # define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ |
28 | # endif |
29 | # |
30 | # if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) |
31 | # define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ |
32 | # elif (__GNUC__ > 4) |
33 | # define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ |
34 | # endif |
35 | # |
36 | # if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) |
37 | # define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ |
38 | # elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) |
39 | # define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ |
40 | # elif (__GNUC__ > 4) |
41 | # define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ |
42 | # endif |
43 | # endif |
44 | # |
45 | # if defined __clang_major__ |
46 | # if (__clang_major__ == 3 && __clang_minor__ >= 5) |
47 | # define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ |
48 | # elif (__clang_major__ > 3) |
49 | # define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ |
50 | # endif |
51 | # if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ |
52 | # define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ |
53 | # elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) |
54 | # define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ |
55 | # endif |
56 | # endif |
57 | # |
58 | # if defined _MSC_VER |
59 | # if (_MSC_VER >= 1900) |
60 | # define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ |
61 | # endif |
62 | # endif |
63 | |
64 | # if defined __clang__ |
65 | # if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) |
66 | # define OPTIONAL_HAS_THIS_RVALUE_REFS 1 |
67 | # else |
68 | # define OPTIONAL_HAS_THIS_RVALUE_REFS 0 |
69 | # endif |
70 | # elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ |
71 | # define OPTIONAL_HAS_THIS_RVALUE_REFS 1 |
72 | # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ |
73 | # define OPTIONAL_HAS_THIS_RVALUE_REFS 1 |
74 | # else |
75 | # define OPTIONAL_HAS_THIS_RVALUE_REFS 0 |
76 | # endif |
77 | |
78 | |
79 | # if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ |
80 | # define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 |
81 | # define OPTIONAL_CONSTEXPR_INIT_LIST constexpr |
82 | # else |
83 | # define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 |
84 | # define OPTIONAL_CONSTEXPR_INIT_LIST |
85 | # endif |
86 | |
87 | # if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) |
88 | # define OPTIONAL_HAS_MOVE_ACCESSORS 1 |
89 | # else |
90 | # define OPTIONAL_HAS_MOVE_ACCESSORS 0 |
91 | # endif |
92 | |
93 | # // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr |
94 | # if (defined __cplusplus) && (__cplusplus == 201103L) |
95 | # define OPTIONAL_MUTABLE_CONSTEXPR |
96 | # else |
97 | # define OPTIONAL_MUTABLE_CONSTEXPR constexpr |
98 | # endif |
99 | |
100 | namespace std{ |
101 | |
102 | namespace experimental{ |
103 | |
104 | // BEGIN workaround for missing is_trivially_destructible |
105 | # if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ |
106 | // leave it: it is already there |
107 | # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ |
108 | // leave it: it is already there |
109 | # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ |
110 | // leave it: it is already there |
111 | # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS |
112 | // leave it: the user doesn't want it |
113 | # else |
114 | template <typename T> |
115 | using is_trivially_destructible = std::has_trivial_destructor<T>; |
116 | # endif |
117 | // END workaround for missing is_trivially_destructible |
118 | |
119 | # if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) |
120 | // leave it; our metafunctions are already defined. |
121 | # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ |
122 | // leave it; our metafunctions are already defined. |
123 | # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ |
124 | // leave it: it is already there |
125 | # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS |
126 | // leave it: the user doesn't want it |
127 | # else |
128 | |
129 | |
130 | // workaround for missing traits in GCC and CLANG |
131 | template <class T> |
132 | struct is_nothrow_move_constructible |
133 | { |
134 | constexpr static bool value = std::is_nothrow_constructible<T, T&&>::value; |
135 | }; |
136 | |
137 | |
138 | template <class T, class U> |
139 | struct is_assignable |
140 | { |
141 | template <class X, class Y> |
142 | constexpr static bool has_assign(...) { return false; } |
143 | |
144 | template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) > |
145 | // the comma operator is necessary for the cases where operator= returns void |
146 | constexpr static bool has_assign(bool) { return true; } |
147 | |
148 | constexpr static bool value = has_assign<T, U>(true); |
149 | }; |
150 | |
151 | |
152 | template <class T> |
153 | struct is_nothrow_move_assignable |
154 | { |
155 | template <class X, bool has_any_move_assign> |
156 | struct has_nothrow_move_assign { |
157 | constexpr static bool value = false; |
158 | }; |
159 | |
160 | template <class X> |
161 | struct has_nothrow_move_assign<X, true> { |
162 | constexpr static bool value = noexcept( std::declval<X&>() = std::declval<X&&>() ); |
163 | }; |
164 | |
165 | constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; |
166 | }; |
167 | // end workaround |
168 | |
169 | |
170 | # endif |
171 | |
172 | |
173 | |
174 | // 20.5.4, optional for object types |
175 | template <class T> class optional; |
176 | |
177 | // 20.5.5, optional for lvalue reference types |
178 | template <class T> class optional<T&>; |
179 | |
180 | |
181 | // workaround: std utility functions aren't constexpr yet |
182 | template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept |
183 | { |
184 | return static_cast<T&&>(t); |
185 | } |
186 | |
187 | template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept |
188 | { |
189 | static_assert(!std::is_lvalue_reference<T>::value, "!!" ); |
190 | return static_cast<T&&>(t); |
191 | } |
192 | |
193 | template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept |
194 | { |
195 | return static_cast<typename std::remove_reference<T>::type&&>(t); |
196 | } |
197 | |
198 | |
199 | #if defined NDEBUG |
200 | # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) |
201 | #else |
202 | # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) |
203 | #endif |
204 | |
205 | |
206 | namespace detail_ |
207 | { |
208 | |
209 | // static_addressof: a constexpr version of addressof |
210 | template <typename T> |
211 | struct has_overloaded_addressof |
212 | { |
213 | template <class X> |
214 | constexpr static bool has_overload(...) { return false; } |
215 | |
216 | template <class X, size_t S = sizeof(std::declval<X&>().operator&()) > |
217 | constexpr static bool has_overload(bool) { return true; } |
218 | |
219 | constexpr static bool value = has_overload<T>(true); |
220 | }; |
221 | |
222 | template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> |
223 | constexpr T* static_addressof(T& ref) |
224 | { |
225 | return &ref; |
226 | } |
227 | |
228 | template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> |
229 | T* static_addressof(T& ref) |
230 | { |
231 | return std::addressof(ref); |
232 | } |
233 | |
234 | |
235 | // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A |
236 | template <class U> |
237 | constexpr U convert(U v) { return v; } |
238 | |
239 | } // namespace detail |
240 | |
241 | |
242 | constexpr struct trivial_init_t{} trivial_init{}; |
243 | |
244 | |
245 | // 20.5.6, In-place construction |
246 | constexpr struct in_place_t{} in_place{}; |
247 | |
248 | |
249 | // 20.5.7, Disengaged state indicator |
250 | struct nullopt_t |
251 | { |
252 | struct init{}; |
253 | constexpr explicit nullopt_t(init){} |
254 | }; |
255 | constexpr nullopt_t nullopt{nullopt_t::init()}; |
256 | |
257 | |
258 | // 20.5.8, class bad_optional_access |
259 | class bad_optional_access : public logic_error { |
260 | public: |
261 | explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} |
262 | explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} |
263 | }; |
264 | |
265 | |
266 | template <class T> |
267 | union storage_t |
268 | { |
269 | unsigned char dummy_; |
270 | T value_; |
271 | |
272 | constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; |
273 | |
274 | template <class... Args> |
275 | constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {} |
276 | |
277 | ~storage_t(){} |
278 | }; |
279 | |
280 | |
281 | template <class T> |
282 | union constexpr_storage_t |
283 | { |
284 | unsigned char dummy_; |
285 | T value_; |
286 | |
287 | constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; |
288 | |
289 | template <class... Args> |
290 | constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {} |
291 | |
292 | ~constexpr_storage_t() = default; |
293 | }; |
294 | |
295 | |
296 | template <class T> |
297 | struct optional_base |
298 | { |
299 | bool init_; |
300 | storage_t<T> storage_; |
301 | |
302 | constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; |
303 | |
304 | explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} |
305 | |
306 | explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} |
307 | |
308 | template <class... Args> explicit optional_base(in_place_t, Args&&... args) |
309 | : init_(true), storage_(constexpr_forward<Args>(args)...) {} |
310 | |
311 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> |
312 | explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) |
313 | : init_(true), storage_(il, std::forward<Args>(args)...) {} |
314 | |
315 | ~optional_base() { if (init_) storage_.value_.T::~T(); } |
316 | }; |
317 | |
318 | |
319 | template <class T> |
320 | struct constexpr_optional_base |
321 | { |
322 | bool init_; |
323 | constexpr_storage_t<T> storage_; |
324 | |
325 | constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; |
326 | |
327 | explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} |
328 | |
329 | explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} |
330 | |
331 | template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) |
332 | : init_(true), storage_(constexpr_forward<Args>(args)...) {} |
333 | |
334 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> |
335 | OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) |
336 | : init_(true), storage_(il, std::forward<Args>(args)...) {} |
337 | |
338 | ~constexpr_optional_base() = default; |
339 | }; |
340 | |
341 | template <class T> |
342 | using OptionalBase = typename std::conditional< |
343 | is_trivially_destructible<T>::value, // if possible |
344 | constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor |
345 | optional_base<typename std::remove_const<T>::type> |
346 | >::type; |
347 | |
348 | |
349 | |
350 | template <class T> |
351 | class optional : private OptionalBase<T> |
352 | { |
353 | static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" ); |
354 | static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T" ); |
355 | |
356 | |
357 | constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; } |
358 | typename std::remove_const<T>::type* dataptr() { return std::addressof(OptionalBase<T>::storage_.value_); } |
359 | constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); } |
360 | |
361 | # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 |
362 | constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; } |
363 | # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 |
364 | OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); } |
365 | OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage_.value_; } |
366 | # else |
367 | T& contained_val() & { return OptionalBase<T>::storage_.value_; } |
368 | T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); } |
369 | # endif |
370 | # else |
371 | constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; } |
372 | T& contained_val() { return OptionalBase<T>::storage_.value_; } |
373 | # endif |
374 | |
375 | void clear() noexcept { |
376 | if (initialized()) dataptr()->T::~T(); |
377 | OptionalBase<T>::init_ = false; |
378 | } |
379 | |
380 | template <class... Args> |
381 | void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...))) |
382 | { |
383 | assert(!OptionalBase<T>::init_); |
384 | ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...); |
385 | OptionalBase<T>::init_ = true; |
386 | } |
387 | |
388 | template <class U, class... Args> |
389 | void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...))) |
390 | { |
391 | assert(!OptionalBase<T>::init_); |
392 | ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...); |
393 | OptionalBase<T>::init_ = true; |
394 | } |
395 | |
396 | public: |
397 | typedef T value_type; |
398 | |
399 | // 20.5.5.1, constructors |
400 | constexpr optional() noexcept : OptionalBase<T>() {}; |
401 | constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {}; |
402 | |
403 | optional(const optional& rhs) |
404 | : OptionalBase<T>() |
405 | { |
406 | if (rhs.initialized()) { |
407 | ::new (static_cast<void*>(dataptr())) T(*rhs); |
408 | OptionalBase<T>::init_ = true; |
409 | } |
410 | } |
411 | |
412 | optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value) |
413 | : OptionalBase<T>() |
414 | { |
415 | if (rhs.initialized()) { |
416 | ::new (static_cast<void*>(dataptr())) T(std::move(*rhs)); |
417 | OptionalBase<T>::init_ = true; |
418 | } |
419 | } |
420 | |
421 | constexpr optional(const T& v) : OptionalBase<T>(v) {} |
422 | |
423 | constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {} |
424 | |
425 | template <class... Args> |
426 | explicit constexpr optional(in_place_t, Args&&... args) |
427 | : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {} |
428 | |
429 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> |
430 | OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args) |
431 | : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {} |
432 | |
433 | // 20.5.4.2, Destructor |
434 | ~optional() = default; |
435 | |
436 | // 20.5.4.3, assignment |
437 | optional& operator=(nullopt_t) noexcept |
438 | { |
439 | clear(); |
440 | return *this; |
441 | } |
442 | |
443 | optional& operator=(const optional& rhs) |
444 | { |
445 | if (initialized() == true && rhs.initialized() == false) clear(); |
446 | else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); |
447 | else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; |
448 | return *this; |
449 | } |
450 | |
451 | optional& operator=(optional&& rhs) |
452 | noexcept(is_nothrow_move_assignable<T>::value && is_nothrow_move_constructible<T>::value) |
453 | { |
454 | if (initialized() == true && rhs.initialized() == false) clear(); |
455 | else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); |
456 | else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); |
457 | return *this; |
458 | } |
459 | |
460 | template <class U> |
461 | auto operator=(U&& v) |
462 | -> typename enable_if |
463 | < |
464 | is_same<typename decay<U>::type, T>::value, |
465 | optional& |
466 | >::type |
467 | { |
468 | if (initialized()) { contained_val() = std::forward<U>(v); } |
469 | else { initialize(std::forward<U>(v)); } |
470 | return *this; |
471 | } |
472 | |
473 | |
474 | template <class... Args> |
475 | void emplace(Args&&... args) |
476 | { |
477 | clear(); |
478 | initialize(std::forward<Args>(args)...); |
479 | } |
480 | |
481 | template <class U, class... Args> |
482 | void emplace(initializer_list<U> il, Args&&... args) |
483 | { |
484 | clear(); |
485 | initialize<U, Args...>(il, std::forward<Args>(args)...); |
486 | } |
487 | |
488 | // 20.5.4.4, Swap |
489 | void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value && noexcept(swap(rhs&: declval<T&>(), declval<T&>()))) |
490 | { |
491 | if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } |
492 | else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } |
493 | else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } |
494 | } |
495 | |
496 | // 20.5.4.5, Observers |
497 | |
498 | explicit constexpr operator bool() const noexcept { return initialized(); } |
499 | constexpr bool has_value() const noexcept { return initialized(); } |
500 | |
501 | constexpr T const* operator ->() const { |
502 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); |
503 | } |
504 | |
505 | # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 |
506 | |
507 | OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { |
508 | assert (initialized()); |
509 | return dataptr(); |
510 | } |
511 | |
512 | constexpr T const& operator *() const& { |
513 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); |
514 | } |
515 | |
516 | OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { |
517 | assert (initialized()); |
518 | return contained_val(); |
519 | } |
520 | |
521 | OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { |
522 | assert (initialized()); |
523 | return constexpr_move(contained_val()); |
524 | } |
525 | |
526 | constexpr T const& value() const& { |
527 | return initialized() ? contained_val() : (throw bad_optional_access("bad optional access" ), contained_val()); |
528 | } |
529 | |
530 | OPTIONAL_MUTABLE_CONSTEXPR T& value() & { |
531 | return initialized() ? contained_val() : (throw bad_optional_access("bad optional access" ), contained_val()); |
532 | } |
533 | |
534 | OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { |
535 | if (!initialized()) throw bad_optional_access("bad optional access" ); |
536 | return std::move(contained_val()); |
537 | } |
538 | |
539 | # else |
540 | |
541 | T* operator ->() { |
542 | assert (initialized()); |
543 | return dataptr(); |
544 | } |
545 | |
546 | constexpr T const& operator *() const { |
547 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); |
548 | } |
549 | |
550 | T& operator *() { |
551 | assert (initialized()); |
552 | return contained_val(); |
553 | } |
554 | |
555 | constexpr T const& value() const { |
556 | return initialized() ? contained_val() : (throw bad_optional_access("bad optional access" ), contained_val()); |
557 | } |
558 | |
559 | T& value() { |
560 | return initialized() ? contained_val() : (throw bad_optional_access("bad optional access" ), contained_val()); |
561 | } |
562 | |
563 | # endif |
564 | |
565 | # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 |
566 | |
567 | template <class V> |
568 | constexpr T value_or(V&& v) const& |
569 | { |
570 | return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); |
571 | } |
572 | |
573 | # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 |
574 | |
575 | template <class V> |
576 | OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && |
577 | { |
578 | return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); |
579 | } |
580 | |
581 | # else |
582 | |
583 | template <class V> |
584 | T value_or(V&& v) && |
585 | { |
586 | return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); |
587 | } |
588 | |
589 | # endif |
590 | |
591 | # else |
592 | |
593 | template <class V> |
594 | constexpr T value_or(V&& v) const |
595 | { |
596 | return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); |
597 | } |
598 | |
599 | # endif |
600 | |
601 | // 20.6.3.6, modifiers |
602 | void reset() noexcept { clear(); } |
603 | }; |
604 | |
605 | |
606 | template <class T> |
607 | class optional<T&> |
608 | { |
609 | static_assert( !std::is_same<T, nullopt_t>::value, "bad T" ); |
610 | static_assert( !std::is_same<T, in_place_t>::value, "bad T" ); |
611 | T* ref; |
612 | |
613 | public: |
614 | |
615 | // 20.5.5.1, construction/destruction |
616 | constexpr optional() noexcept : ref(nullptr) {} |
617 | |
618 | constexpr optional(nullopt_t) noexcept : ref(nullptr) {} |
619 | |
620 | constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} |
621 | |
622 | optional(T&&) = delete; |
623 | |
624 | constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} |
625 | |
626 | explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} |
627 | |
628 | explicit optional(in_place_t, T&&) = delete; |
629 | |
630 | ~optional() = default; |
631 | |
632 | // 20.5.5.2, mutation |
633 | optional& operator=(nullopt_t) noexcept { |
634 | ref = nullptr; |
635 | return *this; |
636 | } |
637 | |
638 | // optional& operator=(const optional& rhs) noexcept { |
639 | // ref = rhs.ref; |
640 | // return *this; |
641 | // } |
642 | |
643 | // optional& operator=(optional&& rhs) noexcept { |
644 | // ref = rhs.ref; |
645 | // return *this; |
646 | // } |
647 | |
648 | template <typename U> |
649 | auto operator=(U&& rhs) noexcept |
650 | -> typename enable_if |
651 | < |
652 | is_same<typename decay<U>::type, optional<T&>>::value, |
653 | optional& |
654 | >::type |
655 | { |
656 | ref = rhs.ref; |
657 | return *this; |
658 | } |
659 | |
660 | template <typename U> |
661 | auto operator=(U&& rhs) noexcept |
662 | -> typename enable_if |
663 | < |
664 | !is_same<typename decay<U>::type, optional<T&>>::value, |
665 | optional& |
666 | >::type |
667 | = delete; |
668 | |
669 | void emplace(T& v) noexcept { |
670 | ref = detail_::static_addressof(v); |
671 | } |
672 | |
673 | void emplace(T&&) = delete; |
674 | |
675 | |
676 | void swap(optional<T&>& rhs) noexcept |
677 | { |
678 | std::swap(ref, rhs.ref); |
679 | } |
680 | |
681 | // 20.5.5.3, observers |
682 | constexpr T* operator->() const { |
683 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); |
684 | } |
685 | |
686 | constexpr T& operator*() const { |
687 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); |
688 | } |
689 | |
690 | constexpr T& value() const { |
691 | return ref ? *ref : (throw bad_optional_access("bad optional access" ), *ref); |
692 | } |
693 | |
694 | explicit constexpr operator bool() const noexcept { |
695 | return ref != nullptr; |
696 | } |
697 | |
698 | constexpr bool has_value() const noexcept { |
699 | return ref != nullptr; |
700 | } |
701 | |
702 | template <class V> |
703 | constexpr typename decay<T>::type value_or(V&& v) const |
704 | { |
705 | return *this ? **this : detail_::convert<typename decay<T>::type>(constexpr_forward<V>(v)); |
706 | } |
707 | |
708 | // x.x.x.x, modifiers |
709 | void reset() noexcept { ref = nullptr; } |
710 | }; |
711 | |
712 | |
713 | template <class T> |
714 | class optional<T&&> |
715 | { |
716 | static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); |
717 | }; |
718 | |
719 | |
720 | // 20.5.8, Relational operators |
721 | template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) |
722 | { |
723 | return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; |
724 | } |
725 | |
726 | template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) |
727 | { |
728 | return !(x == y); |
729 | } |
730 | |
731 | template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) |
732 | { |
733 | return (!y) ? false : (!x) ? true : *x < *y; |
734 | } |
735 | |
736 | template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) |
737 | { |
738 | return (y < x); |
739 | } |
740 | |
741 | template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) |
742 | { |
743 | return !(y < x); |
744 | } |
745 | |
746 | template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) |
747 | { |
748 | return !(x < y); |
749 | } |
750 | |
751 | |
752 | // 20.5.9, Comparison with nullopt |
753 | template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept |
754 | { |
755 | return (!x); |
756 | } |
757 | |
758 | template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept |
759 | { |
760 | return (!x); |
761 | } |
762 | |
763 | template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept |
764 | { |
765 | return bool(x); |
766 | } |
767 | |
768 | template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept |
769 | { |
770 | return bool(x); |
771 | } |
772 | |
773 | template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept |
774 | { |
775 | return false; |
776 | } |
777 | |
778 | template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept |
779 | { |
780 | return bool(x); |
781 | } |
782 | |
783 | template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept |
784 | { |
785 | return (!x); |
786 | } |
787 | |
788 | template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept |
789 | { |
790 | return true; |
791 | } |
792 | |
793 | template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept |
794 | { |
795 | return bool(x); |
796 | } |
797 | |
798 | template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept |
799 | { |
800 | return false; |
801 | } |
802 | |
803 | template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept |
804 | { |
805 | return true; |
806 | } |
807 | |
808 | template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept |
809 | { |
810 | return (!x); |
811 | } |
812 | |
813 | |
814 | |
815 | // 20.5.10, Comparison with T |
816 | template <class T> constexpr bool operator==(const optional<T>& x, const T& v) |
817 | { |
818 | return bool(x) ? *x == v : false; |
819 | } |
820 | |
821 | template <class T> constexpr bool operator==(const T& v, const optional<T>& x) |
822 | { |
823 | return bool(x) ? v == *x : false; |
824 | } |
825 | |
826 | template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) |
827 | { |
828 | return bool(x) ? *x != v : true; |
829 | } |
830 | |
831 | template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) |
832 | { |
833 | return bool(x) ? v != *x : true; |
834 | } |
835 | |
836 | template <class T> constexpr bool operator<(const optional<T>& x, const T& v) |
837 | { |
838 | return bool(x) ? *x < v : true; |
839 | } |
840 | |
841 | template <class T> constexpr bool operator>(const T& v, const optional<T>& x) |
842 | { |
843 | return bool(x) ? v > *x : true; |
844 | } |
845 | |
846 | template <class T> constexpr bool operator>(const optional<T>& x, const T& v) |
847 | { |
848 | return bool(x) ? *x > v : false; |
849 | } |
850 | |
851 | template <class T> constexpr bool operator<(const T& v, const optional<T>& x) |
852 | { |
853 | return bool(x) ? v < *x : false; |
854 | } |
855 | |
856 | template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) |
857 | { |
858 | return bool(x) ? *x >= v : false; |
859 | } |
860 | |
861 | template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) |
862 | { |
863 | return bool(x) ? v <= *x : false; |
864 | } |
865 | |
866 | template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) |
867 | { |
868 | return bool(x) ? *x <= v : true; |
869 | } |
870 | |
871 | template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) |
872 | { |
873 | return bool(x) ? v >= *x : true; |
874 | } |
875 | |
876 | |
877 | // Comparison of optional<T&> with T |
878 | template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) |
879 | { |
880 | return bool(x) ? *x == v : false; |
881 | } |
882 | |
883 | template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) |
884 | { |
885 | return bool(x) ? v == *x : false; |
886 | } |
887 | |
888 | template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) |
889 | { |
890 | return bool(x) ? *x != v : true; |
891 | } |
892 | |
893 | template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) |
894 | { |
895 | return bool(x) ? v != *x : true; |
896 | } |
897 | |
898 | template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) |
899 | { |
900 | return bool(x) ? *x < v : true; |
901 | } |
902 | |
903 | template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) |
904 | { |
905 | return bool(x) ? v > *x : true; |
906 | } |
907 | |
908 | template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) |
909 | { |
910 | return bool(x) ? *x > v : false; |
911 | } |
912 | |
913 | template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) |
914 | { |
915 | return bool(x) ? v < *x : false; |
916 | } |
917 | |
918 | template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) |
919 | { |
920 | return bool(x) ? *x >= v : false; |
921 | } |
922 | |
923 | template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) |
924 | { |
925 | return bool(x) ? v <= *x : false; |
926 | } |
927 | |
928 | template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) |
929 | { |
930 | return bool(x) ? *x <= v : true; |
931 | } |
932 | |
933 | template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) |
934 | { |
935 | return bool(x) ? v >= *x : true; |
936 | } |
937 | |
938 | // Comparison of optional<T const&> with T |
939 | template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) |
940 | { |
941 | return bool(x) ? *x == v : false; |
942 | } |
943 | |
944 | template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) |
945 | { |
946 | return bool(x) ? v == *x : false; |
947 | } |
948 | |
949 | template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) |
950 | { |
951 | return bool(x) ? *x != v : true; |
952 | } |
953 | |
954 | template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) |
955 | { |
956 | return bool(x) ? v != *x : true; |
957 | } |
958 | |
959 | template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) |
960 | { |
961 | return bool(x) ? *x < v : true; |
962 | } |
963 | |
964 | template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) |
965 | { |
966 | return bool(x) ? v > *x : true; |
967 | } |
968 | |
969 | template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) |
970 | { |
971 | return bool(x) ? *x > v : false; |
972 | } |
973 | |
974 | template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) |
975 | { |
976 | return bool(x) ? v < *x : false; |
977 | } |
978 | |
979 | template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) |
980 | { |
981 | return bool(x) ? *x >= v : false; |
982 | } |
983 | |
984 | template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) |
985 | { |
986 | return bool(x) ? v <= *x : false; |
987 | } |
988 | |
989 | template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) |
990 | { |
991 | return bool(x) ? *x <= v : true; |
992 | } |
993 | |
994 | template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) |
995 | { |
996 | return bool(x) ? v >= *x : true; |
997 | } |
998 | |
999 | |
1000 | // 20.5.12, Specialized algorithms |
1001 | template <class T> |
1002 | void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) |
1003 | { |
1004 | x.swap(y); |
1005 | } |
1006 | |
1007 | |
1008 | template <class T> |
1009 | constexpr optional<typename decay<T>::type> make_optional(T&& v) |
1010 | { |
1011 | return optional<typename decay<T>::type>(constexpr_forward<T>(v)); |
1012 | } |
1013 | |
1014 | template <class X> |
1015 | constexpr optional<X&> make_optional(reference_wrapper<X> v) |
1016 | { |
1017 | return optional<X&>(v.get()); |
1018 | } |
1019 | |
1020 | |
1021 | } // namespace experimental |
1022 | } // namespace std |
1023 | |
1024 | namespace std |
1025 | { |
1026 | template <typename T> |
1027 | struct hash<std::experimental::optional<T>> |
1028 | { |
1029 | typedef typename hash<T>::result_type result_type; |
1030 | typedef std::experimental::optional<T> argument_type; |
1031 | |
1032 | constexpr result_type operator()(argument_type const& arg) const { |
1033 | return arg ? std::hash<T>{}(*arg) : result_type{}; |
1034 | } |
1035 | }; |
1036 | |
1037 | template <typename T> |
1038 | struct hash<std::experimental::optional<T&>> |
1039 | { |
1040 | typedef typename hash<T>::result_type result_type; |
1041 | typedef std::experimental::optional<T&> argument_type; |
1042 | |
1043 | constexpr result_type operator()(argument_type const& arg) const { |
1044 | return arg ? std::hash<T>{}(*arg) : result_type{}; |
1045 | } |
1046 | }; |
1047 | } |
1048 | |
1049 | # undef TR2_OPTIONAL_REQUIRES |
1050 | # undef TR2_OPTIONAL_ASSERTED_EXPRESSION |
1051 | |
1052 | # endif //___OPTIONAL_HPP___ |
1053 | |