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