openMSX
optional.hh
Go to the documentation of this file.
1 // This implements the c++17 std::optional class.
2 // https://en.cppreference.com/w/cpp/utility/optional
3 // Thus remove this code once we switch to a c++17 compiler.
4 //
5 // This is a simplified (stripped down) adaptation from:
6 // https://github.com/akrzemi1/Optional/blob/master/optional.hpp
7 //
8 // Original file header:
9 // Copyright (C) 2011 - 2012 Andrzej Krzemienski.
10 //
11 // Use, modification, and distribution is subject to the Boost Software
12 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14 //
15 // The idea and interface is based on Boost.Optional library
16 // authored by Fernando Luis Cacciola Carballal
17 
18 #ifndef OPTIONAL_HH
19 #define OPTIONAL_HH
20 
21 #include <cassert>
22 #include <functional>
23 #include <initializer_list>
24 #include <stdexcept>
25 #include <type_traits>
26 #include <utility>
27 
28 template<typename T> class optional;
29 
30 constexpr struct in_place_t {
31 } in_place{};
32 
33 struct nullopt_t {
34  struct init {};
35  constexpr explicit nullopt_t(init) {}
36 };
38 
39 struct bad_optional_access : std::logic_error
40 {
41  explicit bad_optional_access(const char* what_arg)
42  : logic_error{what_arg} {}
43 };
44 
45 namespace opt_impl {
46 
47 // workaround: std utility functions aren't constexpr yet
48 template<typename T>
49 inline constexpr T&&
50 constexpr_forward(std::remove_reference_t<T>& t) noexcept
51 {
52  return static_cast<T&&>(t);
53 }
54 
55 template<typename T>
56 inline constexpr T&&
57 constexpr_forward(std::remove_reference_t<T>&& t) noexcept
58 {
59  static_assert(!std::is_lvalue_reference<T>::value, "!!");
60  return static_cast<T&&>(t);
61 }
62 
63 template<typename T>
64 inline constexpr std::remove_reference_t<T>&&
65 constexpr_move(T&& t) noexcept
66 {
67  return static_cast<std::remove_reference_t<T>&&>(t);
68 }
69 
70 // static_addressof: a constexpr version of addressof
71 template<typename T> struct has_overloaded_addressof {
72  template<typename X> constexpr static bool has_overload(...)
73  {
74  return false;
75  }
76 
77  template<typename X, size_t S = sizeof(std::declval<X&>().operator&())>
78  constexpr static bool has_overload(bool)
79  {
80  return true;
81  }
82 
83  constexpr static bool value = has_overload<T>(true);
84 };
85 
86 template<typename T,
87  std::enable_if_t<!has_overloaded_addressof<T>::value>* = nullptr>
88 constexpr T* static_addressof(T& ref)
89 {
90  return &ref;
91 }
92 
93 template<typename T,
94  std::enable_if_t<has_overloaded_addressof<T>::value>* = nullptr>
95 T* static_addressof(T& ref)
96 {
97  return std::addressof(ref);
98 }
99 
100 // the call to convert<A>(b) has return type A and converts b to type A iff b
101 // decltype(b) is implicitly convertible to A
102 template<typename U> constexpr U convert(U v)
103 {
104  return v;
105 }
106 
107 namespace swap_ns {
108 using std::swap;
109 template<typename T> void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u)))
110 {
111  swap(t, u);
112 }
113 } // namespace swap_ns
114 
115 constexpr struct trivial_init_t {
116 } trivial_init{};
117 
118 template<typename T> union storage_t {
119  unsigned char dummy_;
121 
122  constexpr storage_t(trivial_init_t) noexcept : dummy_() {}
123 
124  template<typename... Args>
125  constexpr storage_t(Args&&... args)
126  : value_(constexpr_forward<Args>(args)...)
127  {
128  }
129 
131 };
132 
133 template<typename T> union constexpr_storage_t {
134  unsigned char dummy_;
136 
137  constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {}
138 
139  template<typename... Args>
140  constexpr constexpr_storage_t(Args&&... args)
141  : value_(constexpr_forward<Args>(args)...)
142  {
143  }
144 
146 };
147 
148 template<typename T> struct optional_base {
149  bool init_;
151 
152  constexpr optional_base() noexcept
153  : init_(false), storage_(trivial_init)
154  {
155  }
156 
157  explicit constexpr optional_base(const T& v) : init_(true), storage_(v)
158  {
159  }
160 
161  explicit constexpr optional_base(T&& v)
162  : init_(true), storage_(constexpr_move(v))
163  {
164  }
165 
166  template<typename... Args>
167  explicit optional_base(in_place_t, Args&&... args)
168  : init_(true), storage_(constexpr_forward<Args>(args)...)
169  {
170  }
171 
172  template<typename U, typename... Args,
173  std::enable_if_t<std::is_constructible<
174  T, std::initializer_list<U>>::value>* = nullptr>
175  explicit optional_base(in_place_t, std::initializer_list<U> il,
176  Args&&... args)
177  : init_(true), storage_(il, std::forward<Args>(args)...)
178  {
179  }
180 
182  {
183  if (init_) storage_.value_.T::~T();
184  }
185 };
186 
187 template<typename T> struct constexpr_optional_base {
188  bool init_;
190 
191  constexpr constexpr_optional_base() noexcept
192  : init_(false), storage_(trivial_init)
193  {
194  }
195 
196  explicit constexpr constexpr_optional_base(const T& v)
197  : init_(true), storage_(v)
198  {
199  }
200 
201  explicit constexpr constexpr_optional_base(T&& v)
202  : init_(true), storage_(constexpr_move(v))
203  {
204  }
205 
206  template<typename... Args>
207  explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
208  : init_(true), storage_(constexpr_forward<Args>(args)...)
209  {
210  }
211 
212  template<typename U, typename... Args,
213  std::enable_if_t<std::is_constructible<
214  T, std::initializer_list<U>>::value>* = nullptr>
216  std::initializer_list<U> il,
217  Args&&... args)
218  : init_(true), storage_(il, std::forward<Args>(args)...)
219  {
220  }
221 
222  ~constexpr_optional_base() = default;
223 };
224 
225 template<typename T>
226 using OptionalBase = std::conditional_t<
227  std::is_trivially_destructible<T>::value, // if possible
228  constexpr_optional_base<std::remove_const_t<T>>, // use base with trivial destructor
230 
231 } // namespace opt_impl
232 
233 template<typename T> class optional : private opt_impl::OptionalBase<T>
234 {
235  using Base = opt_impl::OptionalBase<T>;
236 
237  static_assert(!std::is_same<std::decay_t<T>, nullopt_t>::value,
238  "bad T");
239  static_assert(!std::is_same<std::decay_t<T>, in_place_t>::value,
240  "bad T");
241 
242  constexpr bool initialized() const noexcept
243  {
244  return Base::init_;
245  }
246  std::remove_const_t<T>* dataptr()
247  {
248  return std::addressof(Base::storage_.value_);
249  }
250  constexpr const T* dataptr() const
251  {
252  return opt_impl::static_addressof(Base::storage_.value_);
253  }
254 
255  constexpr const T& contained_val() const&
256  {
257  return Base::storage_.value_;
258  }
259  constexpr T&& contained_val() &&
260  {
261  return std::move(Base::storage_.value_);
262  }
263  constexpr T& contained_val() &
264  {
265  return Base::storage_.value_;
266  }
267 
268  void clear() noexcept
269  {
270  if (initialized()) dataptr()->T::~T();
271  Base::init_ = false;
272  }
273 
274  template<typename... Args>
275  void initialize(Args&&... args) noexcept(
276  noexcept(T(std::forward<Args>(args)...)))
277  {
278  assert(!Base::init_);
279  ::new (static_cast<void*>(dataptr()))
280  T(std::forward<Args>(args)...);
281  Base::init_ = true;
282  }
283 
284  template<typename U, typename... Args>
285  void initialize(std::initializer_list<U> il, Args&&... args) noexcept(
286  noexcept(T(il, std::forward<Args>(args)...)))
287  {
288  assert(!Base::init_);
289  ::new (static_cast<void*>(dataptr()))
290  T(il, std::forward<Args>(args)...);
291  Base::init_ = true;
292  }
293 
294 public:
295  using value_type = T;
296 
297  constexpr optional() noexcept : Base() {}
298  constexpr optional(nullopt_t) noexcept : Base() {}
299 
300  optional(const optional& rhs) : Base()
301  {
302  if (rhs.initialized()) {
303  ::new (static_cast<void*>(dataptr())) T(*rhs);
304  Base::init_ = true;
305  }
306  }
307 
308  optional(optional&& rhs) noexcept(
309  std::is_nothrow_move_constructible<T>::value)
310  : Base()
311  {
312  if (rhs.initialized()) {
313  ::new (static_cast<void*>(dataptr()))
314  T(std::move(*rhs));
315  Base::init_ = true;
316  }
317  }
318 
319  constexpr optional(const T& v) : Base(v) {}
320 
321  constexpr optional(T&& v) : Base(opt_impl::constexpr_move(v)) {}
322 
323  template<typename... Args>
324  explicit constexpr optional(in_place_t, Args&&... args)
325  : Base(in_place_t{}, opt_impl::constexpr_forward<Args>(args)...)
326  {
327  }
328 
329  template<typename U, typename... Args,
330  std::enable_if_t<std::is_constructible<
331  T, std::initializer_list<U>>::value>* = nullptr>
332  constexpr explicit optional(in_place_t, std::initializer_list<U> il,
333  Args&&... args)
334  : Base(in_place_t{}, il,
335  opt_impl::constexpr_forward<Args>(args)...)
336  {
337  }
338 
339  ~optional() = default;
340 
342  {
343  clear();
344  return *this;
345  }
346 
348  {
349  if (initialized() == true && rhs.initialized() == false)
350  clear();
351  else if (initialized() == false && rhs.initialized() == true)
352  initialize(*rhs);
353  else if (initialized() == true && rhs.initialized() == true)
354  contained_val() = *rhs;
355  return *this;
356  }
357 
358  optional& operator=(optional&& rhs) noexcept(
359  std::is_nothrow_move_assignable<T>::value&&
360  std::is_nothrow_move_constructible<T>::value)
361  {
362  if (initialized() == true && rhs.initialized() == false)
363  clear();
364  else if (initialized() == false && rhs.initialized() == true)
365  initialize(std::move(*rhs));
366  else if (initialized() == true && rhs.initialized() == true)
367  contained_val() = std::move(*rhs);
368  return *this;
369  }
370 
371  template<typename U>
372  auto operator=(U&& v) -> std::enable_if_t<
373  std::is_same<std::decay_t<U>, T>::value, optional&>
374  {
375  if (initialized()) {
376  contained_val() = std::forward<U>(v);
377  } else {
378  initialize(std::forward<U>(v));
379  }
380  return *this;
381  }
382 
383  template<typename... Args> void emplace(Args&&... args)
384  {
385  clear();
386  initialize(std::forward<Args>(args)...);
387  }
388 
389  template<typename U, typename... Args>
390  void emplace(std::initializer_list<U> il, Args&&... args)
391  {
392  clear();
393  initialize<U, Args...>(il, std::forward<Args>(args)...);
394  }
395 
396  void swap(optional<T>& rhs) noexcept(
397  std::is_nothrow_move_constructible<T>::value&& noexcept(
398  opt_impl::swap_ns::adl_swap(std::declval<T&>(),
399  std::declval<T&>())))
400  {
401  if (initialized() == true && rhs.initialized() == false) {
402  rhs.initialize(std::move(**this));
403  clear();
404  } else if (initialized() == false &&
405  rhs.initialized() == true) {
406  initialize(std::move(*rhs));
407  rhs.clear();
408  } else if (initialized() == true && rhs.initialized() == true) {
409  using std::swap;
410  swap(**this, *rhs);
411  }
412  }
413 
414  explicit constexpr operator bool() const noexcept
415  {
416  return initialized();
417  }
418  constexpr bool has_value() const noexcept
419  {
420  return initialized();
421  }
422 
423  constexpr const T* operator->() const
424  {
425  assert(initialized());
426  return dataptr();
427  }
428 
429  constexpr T* operator->()
430  {
431  assert(initialized());
432  return dataptr();
433  }
434 
435  constexpr const T& operator*() const&
436  {
437  assert(initialized());
438  return contained_val();
439  }
440 
441  constexpr T& operator*() &
442  {
443  assert(initialized());
444  return contained_val();
445  }
446 
447  constexpr T&& operator*() &&
448  {
449  assert(initialized());
450  return opt_impl::constexpr_move(contained_val());
451  }
452 
453  constexpr const T& value() const&
454  {
455  return initialized() ? contained_val()
456  : (throw bad_optional_access(
457  "bad optional access"),
458  contained_val());
459  }
460 
461  constexpr T& value() &
462  {
463  return initialized() ? contained_val()
464  : (throw bad_optional_access(
465  "bad optional access"),
466  contained_val());
467  }
468 
469  constexpr T&& value() &&
470  {
471  if (!initialized()) {
472  throw bad_optional_access("bad optional access");
473  }
474  return std::move(contained_val());
475  }
476 
477  template<typename V> constexpr T value_or(V&& v) const&
478  {
479  return *this ? **this
480  : opt_impl::convert<T>(
481  opt_impl::constexpr_forward<V>(v));
482  }
483 
484  template<typename V> constexpr T value_or(V&& v) &&
485  {
486  return *this ? opt_impl::constexpr_move(
487  const_cast<optional<T>&>(*this)
488  .contained_val())
489  : opt_impl::convert<T>(
490  opt_impl::constexpr_forward<V>(v));
491  }
492 
493  void reset() noexcept { clear(); }
494 };
495 
496 template<typename T> class optional<T&>
497 {
498  static_assert(sizeof(T) == 0, "optional references disallowed");
499 };
500 
501 // Relational operators
502 template<typename T>
503 constexpr bool operator==(const optional<T>& x, const optional<T>& y)
504 {
505  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
506 }
507 
508 template<typename T>
509 constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
510 {
511  return !(x == y);
512 }
513 
514 template<typename T>
515 constexpr bool operator<(const optional<T>& x, const optional<T>& y)
516 {
517  return (!y) ? false : (!x) ? true : *x < *y;
518 }
519 
520 template<typename T>
521 constexpr bool operator>(const optional<T>& x, const optional<T>& y)
522 {
523  return (y < x);
524 }
525 
526 template<typename T>
527 constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
528 {
529  return !(y < x);
530 }
531 
532 template<typename T>
533 constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
534 {
535  return !(x < y);
536 }
537 
538 // Comparison with nullopt
539 template<typename T>
540 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
541 {
542  return (!x);
543 }
544 
545 template<typename T>
546 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
547 {
548  return (!x);
549 }
550 
551 template<typename T>
552 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
553 {
554  return bool(x);
555 }
556 
557 template<typename T>
558 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
559 {
560  return bool(x);
561 }
562 
563 template<typename T>
564 constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
565 {
566  return false;
567 }
568 
569 template<typename T>
570 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
571 {
572  return bool(x);
573 }
574 
575 template<typename T>
576 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
577 {
578  return (!x);
579 }
580 
581 template<typename T>
582 constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
583 {
584  return true;
585 }
586 
587 template<typename T>
588 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
589 {
590  return bool(x);
591 }
592 
593 template<typename T>
594 constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
595 {
596  return false;
597 }
598 
599 template<typename T>
600 constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
601 {
602  return true;
603 }
604 
605 template<typename T>
606 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
607 {
608  return (!x);
609 }
610 
611 // Comparison with T
612 template<typename T> constexpr bool operator==(const optional<T>& x, const T& v)
613 {
614  return bool(x) ? *x == v : false;
615 }
616 
617 template<typename T> constexpr bool operator==(const T& v, const optional<T>& x)
618 {
619  return bool(x) ? v == *x : false;
620 }
621 
622 template<typename T> constexpr bool operator!=(const optional<T>& x, const T& v)
623 {
624  return bool(x) ? *x != v : true;
625 }
626 
627 template<typename T> constexpr bool operator!=(const T& v, const optional<T>& x)
628 {
629  return bool(x) ? v != *x : true;
630 }
631 
632 template<typename T> constexpr bool operator<(const optional<T>& x, const T& v)
633 {
634  return bool(x) ? *x < v : true;
635 }
636 
637 template<typename T> constexpr bool operator>(const T& v, const optional<T>& x)
638 {
639  return bool(x) ? v > *x : true;
640 }
641 
642 template<typename T> constexpr bool operator>(const optional<T>& x, const T& v)
643 {
644  return bool(x) ? *x > v : false;
645 }
646 
647 template<typename T> constexpr bool operator<(const T& v, const optional<T>& x)
648 {
649  return bool(x) ? v < *x : false;
650 }
651 
652 template<typename T> constexpr bool operator>=(const optional<T>& x, const T& v)
653 {
654  return bool(x) ? *x >= v : false;
655 }
656 
657 template<typename T> constexpr bool operator<=(const T& v, const optional<T>& x)
658 {
659  return bool(x) ? v <= *x : false;
660 }
661 
662 template<typename T> constexpr bool operator<=(const optional<T>& x, const T& v)
663 {
664  return bool(x) ? *x <= v : true;
665 }
666 
667 template<typename T> constexpr bool operator>=(const T& v, const optional<T>& x)
668 {
669  return bool(x) ? v >= *x : true;
670 }
671 
672 // Comparison of optional<T&> with T
673 template<typename T>
674 constexpr bool operator==(const optional<T&>& x, const T& v)
675 {
676  return bool(x) ? *x == v : false;
677 }
678 
679 template<typename T>
680 constexpr bool operator==(const T& v, const optional<T&>& x)
681 {
682  return bool(x) ? v == *x : false;
683 }
684 
685 template<typename T>
686 constexpr bool operator!=(const optional<T&>& x, const T& v)
687 {
688  return bool(x) ? *x != v : true;
689 }
690 
691 template<typename T>
692 constexpr bool operator!=(const T& v, const optional<T&>& x)
693 {
694  return bool(x) ? v != *x : true;
695 }
696 
697 template<typename T> constexpr bool operator<(const optional<T&>& x, const T& v)
698 {
699  return bool(x) ? *x < v : true;
700 }
701 
702 template<typename T> constexpr bool operator>(const T& v, const optional<T&>& x)
703 {
704  return bool(x) ? v > *x : true;
705 }
706 
707 template<typename T> constexpr bool operator>(const optional<T&>& x, const T& v)
708 {
709  return bool(x) ? *x > v : false;
710 }
711 
712 template<typename T> constexpr bool operator<(const T& v, const optional<T&>& x)
713 {
714  return bool(x) ? v < *x : false;
715 }
716 
717 template<typename T>
718 constexpr bool operator>=(const optional<T&>& x, const T& v)
719 {
720  return bool(x) ? *x >= v : false;
721 }
722 
723 template<typename T>
724 constexpr bool operator<=(const T& v, const optional<T&>& x)
725 {
726  return bool(x) ? v <= *x : false;
727 }
728 
729 template<typename T>
730 constexpr bool operator<=(const optional<T&>& x, const T& v)
731 {
732  return bool(x) ? *x <= v : true;
733 }
734 
735 template<typename T>
736 constexpr bool operator>=(const T& v, const optional<T&>& x)
737 {
738  return bool(x) ? v >= *x : true;
739 }
740 
741 // Comparison of optional<const T&> with T
742 template<typename T>
743 constexpr bool operator==(const optional<const T&>& x, const T& v)
744 {
745  return bool(x) ? *x == v : false;
746 }
747 
748 template<typename T>
749 constexpr bool operator==(const T& v, const optional<const T&>& x)
750 {
751  return bool(x) ? v == *x : false;
752 }
753 
754 template<typename T>
755 constexpr bool operator!=(const optional<const T&>& x, const T& v)
756 {
757  return bool(x) ? *x != v : true;
758 }
759 
760 template<typename T>
761 constexpr bool operator!=(const T& v, const optional<const T&>& x)
762 {
763  return bool(x) ? v != *x : true;
764 }
765 
766 template<typename T>
767 constexpr bool operator<(const optional<const T&>& x, const T& v)
768 {
769  return bool(x) ? *x < v : true;
770 }
771 
772 template<typename T>
773 constexpr bool operator>(const T& v, const optional<const T&>& x)
774 {
775  return bool(x) ? v > *x : true;
776 }
777 
778 template<typename T>
779 constexpr bool operator>(const optional<const T&>& x, const T& v)
780 {
781  return bool(x) ? *x > v : false;
782 }
783 
784 template<typename T>
785 constexpr bool operator<(const T& v, const optional<const T&>& x)
786 {
787  return bool(x) ? v < *x : false;
788 }
789 
790 template<typename T>
791 constexpr bool operator>=(const optional<const T&>& x, const T& v)
792 {
793  return bool(x) ? *x >= v : false;
794 }
795 
796 template<typename T>
797 constexpr bool operator<=(const T& v, const optional<const T&>& x)
798 {
799  return bool(x) ? v <= *x : false;
800 }
801 
802 template<typename T>
803 constexpr bool operator<=(const optional<const T&>& x, const T& v)
804 {
805  return bool(x) ? *x <= v : true;
806 }
807 
808 template<typename T>
809 constexpr bool operator>=(const T& v, const optional<const T&>& x)
810 {
811  return bool(x) ? v >= *x : true;
812 }
813 
814 // Specialized algorithms
815 template<typename T>
816 void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
817 {
818  x.swap(y);
819 }
820 
821 template<typename T>
823 {
824  return optional<std::decay_t<T>>(
825  opt_impl::constexpr_forward<T>(v));
826 }
827 
828 namespace std {
829 
830 template<typename T> struct hash<::optional<T>> {
831  using result_type = typename hash<T>::result_type;
833 
834  constexpr result_type operator()(const argument_type& arg) const
835  {
836  return arg ? std::hash<T>{}(*arg) : result_type{};
837  }
838 };
839 
840 template<typename T> struct hash<::optional<T&>> {
841  using result_type = typename hash<T>::result_type;
843 
844  constexpr result_type operator()(const argument_type& arg) const
845  {
846  return arg ? std::hash<T>{}(*arg) : result_type{};
847  }
848 };
849 
850 } // namespace std
851 
852 #endif
constexpr result_type operator()(const argument_type &arg) const
Definition: optional.hh:844
constexpr T && value() &&
Definition: optional.hh:469
optional & operator=(const optional &rhs)
Definition: optional.hh:347
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
Definition: optional.hh:816
std::conditional_t< std::is_trivially_destructible< T >::value, constexpr_optional_base< std::remove_const_t< T > >, optional_base< std::remove_const_t< T > >> OptionalBase
Definition: optional.hh:229
constexpr constexpr_optional_base(const T &v)
Definition: optional.hh:196
static constexpr bool has_overload(bool)
Definition: optional.hh:78
constexpr constexpr_storage_t(Args &&... args)
Definition: optional.hh:140
constexpr constexpr_optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: optional.hh:215
void reset() noexcept
Definition: optional.hh:493
constexpr bool operator==(const optional< T > &x, const optional< T > &y)
Definition: optional.hh:503
constexpr optional(in_place_t, Args &&... args)
Definition: optional.hh:324
constexpr constexpr_optional_base(in_place_t, Args &&... args)
Definition: optional.hh:207
constexpr T * operator->()
Definition: optional.hh:429
constexpr constexpr_optional_base() noexcept
Definition: optional.hh:191
constexpr optional() noexcept
Definition: optional.hh:297
constexpr struct in_place_t in_place
STL namespace.
constexpr optional(T &&v)
Definition: optional.hh:321
constexpr_storage_t< T > storage_
Definition: optional.hh:189
constexpr T value_or(V &&v) &&
Definition: optional.hh:484
bad_optional_access(const char *what_arg)
Definition: optional.hh:41
constexpr optional< std::decay_t< T > > make_optional(T &&v)
Definition: optional.hh:822
constexpr result_type operator()(const argument_type &arg) const
Definition: optional.hh:834
constexpr T && constexpr_forward(std::remove_reference_t< T > &&t) noexcept
Definition: optional.hh:57
unsigned char dummy_
Definition: optional.hh:119
optional & operator=(optional &&rhs) noexcept(std::is_nothrow_move_assignable< T >::value &&std::is_nothrow_move_constructible< T >::value)
Definition: optional.hh:358
constexpr optional_base(T &&v)
Definition: optional.hh:161
constexpr T value_or(V &&v) const &
Definition: optional.hh:477
constexpr U convert(U v)
Definition: optional.hh:102
void emplace(Args &&... args)
Definition: optional.hh:383
constexpr const T & value() const &
Definition: optional.hh:453
optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: optional.hh:175
optional & operator=(nullopt_t) noexcept
Definition: optional.hh:341
storage_t< T > storage_
Definition: optional.hh:150
constexpr bool operator!=(const optional< T > &x, const optional< T > &y)
Definition: optional.hh:509
constexpr std::remove_reference_t< T > && constexpr_move(T &&t) noexcept
Definition: optional.hh:65
constexpr optional(const T &v)
Definition: optional.hh:319
constexpr T && operator*() &&
Definition: optional.hh:447
constexpr storage_t(trivial_init_t) noexcept
Definition: optional.hh:122
constexpr const T & operator*() const &
Definition: optional.hh:435
void adl_swap(T &t, T &u) noexcept(noexcept(swap(t, u)))
Definition: optional.hh:109
void emplace(std::initializer_list< U > il, Args &&... args)
Definition: optional.hh:390
typename hash< T >::result_type result_type
Definition: optional.hh:841
constexpr storage_t(Args &&... args)
Definition: optional.hh:125
constexpr bool operator>(const optional< T > &x, const optional< T > &y)
Definition: optional.hh:521
constexpr T & value() &
Definition: optional.hh:461
constexpr T * static_addressof(T &ref)
Definition: optional.hh:88
T * static_addressof(T &ref)
Definition: optional.hh:95
void swap(optional< T > &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&noexcept(opt_impl::swap_ns::adl_swap(std::declval< T &>(), std::declval< T &>())))
Definition: optional.hh:396
constexpr const T * operator->() const
Definition: optional.hh:423
constexpr constexpr_storage_t(trivial_init_t) noexcept
Definition: optional.hh:137
optional_base(in_place_t, Args &&... args)
Definition: optional.hh:167
constexpr optional_base(const T &v)
Definition: optional.hh:157
constexpr nullopt_t nullopt
Definition: optional.hh:37
constexpr bool has_value() const noexcept
Definition: optional.hh:418
constexpr constexpr_optional_base(T &&v)
Definition: optional.hh:201
static constexpr bool has_overload(...)
Definition: optional.hh:72
auto operator=(U &&v) -> std::enable_if_t< std::is_same< std::decay_t< U >, T >::value, optional &>
Definition: optional.hh:372
optional(const optional &rhs)
Definition: optional.hh:300
constexpr bool operator>=(const optional< T > &x, const optional< T > &y)
Definition: optional.hh:533
constexpr optional_base() noexcept
Definition: optional.hh:152
constexpr struct opt_impl::trivial_init_t trivial_init
typename hash< T >::result_type result_type
Definition: optional.hh:831
TclObject t
constexpr optional(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: optional.hh:332
T value_type
Definition: optional.hh:295
constexpr optional(nullopt_t) noexcept
Definition: optional.hh:298
constexpr T & operator*() &
Definition: optional.hh:441
constexpr nullopt_t(init)
Definition: optional.hh:35
optional(optional &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition: optional.hh:308