General Utility Library for C++14  2.12
optional.h
Go to the documentation of this file.
1 
27 #ifndef GUL14_OPTIONAL_H_
28 #define GUL14_OPTIONAL_H_
29 
30 #include <cassert>
31 #include <functional>
32 #include <initializer_list>
33 #include <stdexcept>
34 #include <string>
35 #include <type_traits>
36 #include <utility>
37 
38 #include "gul14/internal.h"
39 #include "gul14/utility.h"
40 
42 #define GUL_OPTIONAL_REQUIRES(...) typename std::enable_if<__VA_ARGS__::value, bool>::type = false
44 
45 namespace gul14 {
46 
54 
55 template <class T>
56 class optional;
57 
58 // 20.5.5, optional for lvalue reference types
59 template <class T>
60 class optional<T&>;
61 
62 
63 // workaround: std utility functions aren't constexpr yet
64 
65 template <class T>
66 inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept {
67  return static_cast<T&&> (t);
68 }
69 
70 template <class T>
71 inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept {
72  static_assert(!std::is_lvalue_reference<T>::value, "!!");
73  return static_cast<T&&> (t);
74 }
75 
76 template <class T>
77 inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept {
78  return static_cast<typename std::remove_reference<T>::type&&> (t);
79 }
80 
81 
82 #if defined NDEBUG
83 #define GUL_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
84 #else
85 #define GUL_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
86 #endif
87 
88 
89 namespace detail_ {
90 
91 // static_addressof: a constexpr version of addressof
92 
93 template <typename T>
94 struct has_overloaded_addressof {
95 
96  template <class X>
97  constexpr static bool has_overload(...) {
98  return false;
99  }
100 
101  template <class X, size_t S = sizeof (std::declval<X&>().operator&()) >
102  constexpr static bool has_overload(bool) {
103  return true;
104  }
105 
106  constexpr static bool value = has_overload<T>(true);
107 };
108 
109 template <typename T, GUL_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
110 constexpr T* static_addressof(T& ref) {
111  return &ref;
112 }
113 
114 template <typename T, GUL_OPTIONAL_REQUIRES(has_overloaded_addressof<T>) >
115 T* static_addressof(T& ref) {
116  return std::addressof(ref);
117 }
118 
119 
120 // 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
121 
122 template <class U>
123 constexpr U convert(U v) {
124  return v;
125 }
126 
127 
128 namespace swap_ns {
129 using std::swap;
130 
131 template <class T>
132 void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u))) {
133  swap(t, u);
134 }
135 
136 } // namespace swap_ns
137 
138 } // namespace detail
139 
140 constexpr struct trivial_init_t {
141 } trivial_init{};
142 
143 
144 // 20.5.7, Disengaged state indicator
145 
146 struct nullopt_t {
147 
148  struct init {
149  };
150 
151  constexpr explicit nullopt_t(init) {
152  }
153 };
154 constexpr nullopt_t nullopt{nullopt_t::init()};
155 
156 
157 // 20.5.8, class bad_optional_access
158 
159 class bad_optional_access : public std::logic_error {
160 public:
161  explicit bad_optional_access(const std::string& what_arg) : std::logic_error{what_arg}
162  {
163  }
164  explicit bad_optional_access(const char* what_arg) : std::logic_error{what_arg}
165  {
166  }
167 };
168 
169 template <class T>
170 union storage_t {
171  unsigned char dummy_;
172  T value_;
173 
174  constexpr storage_t(trivial_init_t) noexcept : dummy_() {
175  };
176 
177  template <class... Args>
178  constexpr storage_t(Args&&... args) : value_(constexpr_forward<Args>(args)...) {
179  }
180 
181  ~storage_t() {
182  }
183 };
184 
185 template <class T>
186 union constexpr_storage_t {
187  unsigned char dummy_;
188  T value_;
189 
190  constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {
191  };
192 
193  template <class... Args>
194  constexpr constexpr_storage_t(Args&&... args) : value_(constexpr_forward<Args>(args)...) {
195  }
196 
197  ~constexpr_storage_t() = default;
198 };
199 
200 template <class T>
201 struct optional_base {
202  bool init_;
203  storage_t<T> storage_;
204 
205  constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {
206  };
207 
208  explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {
209  }
210 
211  explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {
212  }
213 
214  template <class... Args> explicit optional_base(in_place_t, Args&&... args)
215  : init_(true), storage_(constexpr_forward<Args>(args)...) {
216  }
217 
218  template <class U, class... Args, GUL_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
219  explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
220  : init_(true), storage_(il, std::forward<Args>(args)...) {
221  }
222 
223  ~optional_base() {
224  if (init_) storage_.value_.T::~T();
225  }
226 };
227 
228 template <class T>
229 struct constexpr_optional_base {
230  bool init_;
231  constexpr_storage_t<T> storage_;
232 
233  constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {
234  };
235 
236  explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {
237  }
238 
239  explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {
240  }
241 
242  template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
243  : init_(true), storage_(constexpr_forward<Args>(args)...) {
244  }
245 
246  template <class U, class... Args, GUL_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
247  constexpr explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
248  : init_(true), storage_(il, std::forward<Args>(args)...) {
249  }
250 
251  ~constexpr_optional_base() = default;
252 };
253 
254 template <class T>
255 using OptionalBase = typename std::conditional<
256  std::is_trivially_destructible<T>::value, // if possible
257  constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor
258  optional_base<typename std::remove_const<T>::type>
259 >::type;
260 
261 
263 
273 template <class T>
274 class optional : private OptionalBase<T> {
276  static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T");
277  static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T");
278 
279  constexpr bool initialized() const noexcept {
280  return OptionalBase<T>::init_;
281  }
282 
283  typename std::remove_const<T>::type* dataptr() {
284  return std::addressof(OptionalBase<T>::storage_.value_);
285  }
286 
287  constexpr const T* dataptr() const {
288  return detail_::static_addressof(OptionalBase<T>::storage_.value_);
289  }
290 
291  constexpr const T& contained_val() const& {
292  return OptionalBase<T>::storage_.value_;
293  }
294 
295  constexpr T&& contained_val() && {
296  return std::move(OptionalBase<T>::storage_.value_);
297  }
298 
299  constexpr T& contained_val() & {
300  return OptionalBase<T>::storage_.value_;
301  }
302 
303  void clear() noexcept {
304  if (initialized()) dataptr()->T::~T();
305  OptionalBase<T>::init_ = false;
306  }
307 
308  template <class... Args>
309  void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
310  assert(!OptionalBase<T>::init_);
311  ::new (static_cast<void*> (dataptr())) T(std::forward<Args>(args)...);
312  OptionalBase<T>::init_ = true;
313  }
314 
315  template <class U, class... Args>
316  void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...))) {
317  assert(!OptionalBase<T>::init_);
318  ::new (static_cast<void*> (dataptr())) T(il, std::forward<Args>(args)...);
319  OptionalBase<T>::init_ = true;
320  }
321 
322 public:
323  typedef T value_type;
324 
325  // 20.5.5.1, constructors
326 
327  constexpr optional() noexcept : OptionalBase<T>() {
328  };
329 
330  constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {
331  };
332 
333  optional(const optional& rhs)
334  : OptionalBase<T>() {
335  if (rhs.initialized()) {
336  ::new (static_cast<void*> (dataptr())) T(*rhs);
337  OptionalBase<T>::init_ = true;
338  }
339  }
340 
341  optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value)
342  : OptionalBase<T>() {
343  if (rhs.initialized()) {
344  ::new (static_cast<void*> (dataptr())) T(std::move(*rhs));
345  OptionalBase<T>::init_ = true;
346  }
347  }
348 
349  constexpr optional(const T& v) : OptionalBase<T>(v) {
350  }
351 
352  constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {
353  }
354 
355  template <class... Args>
356  explicit constexpr optional(in_place_t, Args&&... args)
357  : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {
358  }
359 
360  template <class U, class... Args, GUL_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
361  constexpr explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
362  : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {
363  }
364 
365  // 20.5.4.2, Destructor
366  ~optional() = default;
367 
368  // 20.5.4.3, assignment
369 
370  optional& operator=(nullopt_t) noexcept {
371  clear();
372  return *this;
373  }
374 
375  optional& operator=(const optional& rhs) {
376  if (initialized() == true && rhs.initialized() == false) clear();
377  else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
378  else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
379  return *this;
380  }
381 
382  optional& operator=(optional&& rhs)
383  noexcept(std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value) {
384  if (initialized() == true && rhs.initialized() == false) clear();
385  else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs));
386  else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs);
387  return *this;
388  }
389 
390  template <class U>
391  auto operator=(U&& v)
392  -> typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value, optional&>::type {
393  if (initialized()) {
394  contained_val() = std::forward<U>(v);
395  } else {
396  initialize(std::forward<U>(v));
397  }
398  return *this;
399  }
400 
401  template <class... Args>
402  void emplace(Args&&... args) {
403  clear();
404  initialize(std::forward<Args>(args)...);
405  }
406 
407  template <class U, class... Args>
408  void emplace(std::initializer_list<U> il, Args&&... args) {
409  clear();
410  initialize<U, Args...>(il, std::forward<Args>(args)...);
411  }
412 
413  // 20.5.4.4, Swap
414 
415  void swap(optional<T>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value
416  && noexcept(detail_::swap_ns::adl_swap(std::declval<T&>(), std::declval<T&>()))) {
417  if (initialized() == true && rhs.initialized() == false) {
418  rhs.initialize(std::move(* * this));
419  clear();
420  } else if (initialized() == false && rhs.initialized() == true) {
421  initialize(std::move(*rhs));
422  rhs.clear();
423  } else if (initialized() == true && rhs.initialized() == true) {
424  using std::swap;
425  swap(* * this, *rhs);
426  }
427  }
428 
429  // 20.5.4.5, Observers
430 
431  explicit constexpr operator bool() const noexcept {
432  return initialized();
433  }
434 
435  constexpr bool has_value() const noexcept {
436  return initialized();
437  }
438 
439  constexpr T const* operator->() const {
440  return GUL_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
441  }
442 
443  constexpr T* operator->() {
444  assert(initialized());
445  return dataptr();
446  }
447 
448  constexpr T const& operator*() const& {
449  return GUL_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
450  }
451 
452  constexpr T& operator*() & {
453  assert(initialized());
454  return contained_val();
455  }
456 
457  constexpr T&& operator*() && {
458  assert(initialized());
459  return constexpr_move(contained_val());
460  }
461 
462  constexpr T const& value() const& {
463  return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
464  }
465 
466  constexpr T& value() & {
467  if (!initialized()) throw bad_optional_access("bad optional access");
468  return contained_val();
469  }
470 
471  constexpr T&& value() && {
472  if (!initialized()) throw bad_optional_access("bad optional access");
473  return std::move(contained_val());
474  }
475 
476 #ifdef _MSC_VER
477 #pragma warning(push)
478 #pragma warning(disable: 4244) // possible loss of data
479 #endif
480 
481  template <class V>
482  constexpr T value_or(V&& v) const& {
483  return *this ? * * this : detail_::convert<T>(constexpr_forward<V>(v));
484  }
485 
486  template <class V>
487  constexpr T value_or(V&& v) && {
488  return *this ? constexpr_move(const_cast<optional<T>&> (*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
489  }
490 #ifdef _MSC_VER
491 #pragma warning(pop)
492 #endif
493 
494  // 20.6.3.6, modifiers
495 
496  void reset() noexcept {
497  clear();
498  }
499 
501 };
502 
512 template <class T>
513 class optional<T&> {
515  static_assert( !std::is_same<T, nullopt_t>::value, "bad T");
516  static_assert( !std::is_same<T, in_place_t>::value, "bad T");
517  T* ref;
518 
519 public:
520 
521  // 20.5.5.1, construction/destruction
522 
523  constexpr optional() noexcept : ref(nullptr) {
524  }
525 
526  constexpr optional(nullopt_t) noexcept : ref(nullptr) {
527  }
528 
529  constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {
530  }
531 
532  optional(T&&) = delete;
533 
534  constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {
535  }
536 
537  explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {
538  }
539 
540  explicit optional(in_place_t, T&&) = delete;
541 
542  ~optional() = default;
543 
544  // 20.5.5.2, mutation
545 
546  optional& operator=(nullopt_t) noexcept {
547  ref = nullptr;
548  return *this;
549  }
550 
551  // optional& operator=(const optional& rhs) noexcept {
552  // ref = rhs.ref;
553  // return *this;
554  // }
555 
556  // optional& operator=(optional&& rhs) noexcept {
557  // ref = rhs.ref;
558  // return *this;
559  // }
560 
561  template <typename U>
562  auto operator=(U&& rhs) noexcept
563  -> typename std::enable_if
564  <
565  std::is_same<typename std::decay<U>::type, optional<T&>>::value,
566  optional&
567  >::type
568  {
569  ref = rhs.ref;
570  return *this;
571  }
572 
573  template <typename U>
574  auto operator=(U&& rhs) noexcept
575  -> typename std::enable_if
576  <
577  !std::is_same<typename std::decay<U>::type, optional<T&>>::value,
578  optional&
579  >::type
580  = delete;
581 
582  void emplace(T& v) noexcept {
583  ref = detail_::static_addressof(v);
584  }
585 
586  void emplace(T&&) = delete;
587 
588  void swap(optional<T&>& rhs) noexcept {
589  std::swap(ref, rhs.ref);
590  }
591 
592  // 20.5.5.3, observers
593 
594  constexpr T* operator->() const {
595  return GUL_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
596  }
597 
598  constexpr T& operator*() const {
599  return GUL_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
600  }
601 
602  constexpr T& value() const {
603  return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
604  }
605 
606  explicit constexpr operator bool() const noexcept {
607  return ref != nullptr;
608  }
609 
610  constexpr bool has_value() const noexcept {
611  return ref != nullptr;
612  }
613 
614  template <class V>
615  constexpr typename std::decay<T>::type value_or(V&& v) const {
616  return *this ? * * this : detail_::convert<typename std::decay<T>::type > (constexpr_forward<V>(v));
617  }
618 
619  // x.x.x.x, modifiers
620 
621  void reset() noexcept {
622  ref = nullptr;
623  }
624 
626 };
627 
629 
630 template <class T>
631 class optional<T&&> {
632  static_assert( sizeof (T) == 0, "optional rvalue references disallowed");
633 };
634 
635 
636 // 20.5.8, Relational operators
637 
638 template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
639  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
640 }
641 
642 template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
643  return !(x == y);
644 }
645 
646 template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
647  return (!y) ? false : (!x) ? true : *x < *y;
648 }
649 
650 template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
651  return (y < x);
652 }
653 
654 template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
655  return !(y < x);
656 }
657 
658 template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
659  return !(x < y);
660 }
661 
662 
663 // 20.5.9, Comparison with nullopt
664 
665 template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
666  return (!x);
667 }
668 
669 template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
670  return (!x);
671 }
672 
673 template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
674  return bool(x);
675 }
676 
677 template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
678  return bool(x);
679 }
680 
681 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
682  return false;
683 }
684 
685 template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
686  return bool(x);
687 }
688 
689 template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
690  return (!x);
691 }
692 
693 template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
694  return true;
695 }
696 
697 template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
698  return bool(x);
699 }
700 
701 template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
702  return false;
703 }
704 
705 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
706  return true;
707 }
708 
709 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
710  return (!x);
711 }
712 
713 
714 
715 // 20.5.10, Comparison with T
716 
717 template <class T> constexpr bool operator==(const optional<T>& x, const T& v) {
718  return bool(x) ? *x == v : false;
719 }
720 
721 template <class T> constexpr bool operator==(const T& v, const optional<T>& x) {
722  return bool(x) ? v == *x : false;
723 }
724 
725 template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) {
726  return bool(x) ? *x != v : true;
727 }
728 
729 template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) {
730  return bool(x) ? v != *x : true;
731 }
732 
733 template <class T> constexpr bool operator<(const optional<T>& x, const T& v) {
734  return bool(x) ? *x < v : true;
735 }
736 
737 template <class T> constexpr bool operator>(const T& v, const optional<T>& x) {
738  return bool(x) ? v > *x : true;
739 }
740 
741 template <class T> constexpr bool operator>(const optional<T>& x, const T& v) {
742  return bool(x) ? *x > v : false;
743 }
744 
745 template <class T> constexpr bool operator<(const T& v, const optional<T>& x) {
746  return bool(x) ? v < *x : false;
747 }
748 
749 template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) {
750  return bool(x) ? *x >= v : false;
751 }
752 
753 template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) {
754  return bool(x) ? v <= *x : false;
755 }
756 
757 template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) {
758  return bool(x) ? *x <= v : true;
759 }
760 
761 template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) {
762  return bool(x) ? v >= *x : true;
763 }
764 
765 
766 // Comparison of optional<T&> with T
767 
768 template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) {
769  return bool(x) ? *x == v : false;
770 }
771 
772 template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) {
773  return bool(x) ? v == *x : false;
774 }
775 
776 template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) {
777  return bool(x) ? *x != v : true;
778 }
779 
780 template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) {
781  return bool(x) ? v != *x : true;
782 }
783 
784 template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) {
785  return bool(x) ? *x < v : true;
786 }
787 
788 template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) {
789  return bool(x) ? v > *x : true;
790 }
791 
792 template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) {
793  return bool(x) ? *x > v : false;
794 }
795 
796 template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) {
797  return bool(x) ? v < *x : false;
798 }
799 
800 template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) {
801  return bool(x) ? *x >= v : false;
802 }
803 
804 template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) {
805  return bool(x) ? v <= *x : false;
806 }
807 
808 template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) {
809  return bool(x) ? *x <= v : true;
810 }
811 
812 template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) {
813  return bool(x) ? v >= *x : true;
814 }
815 
816 // Comparison of optional<T const&> with T
817 
818 template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) {
819  return bool(x) ? *x == v : false;
820 }
821 
822 template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) {
823  return bool(x) ? v == *x : false;
824 }
825 
826 template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) {
827  return bool(x) ? *x != v : true;
828 }
829 
830 template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) {
831  return bool(x) ? v != *x : true;
832 }
833 
834 template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) {
835  return bool(x) ? *x < v : true;
836 }
837 
838 template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) {
839  return bool(x) ? v > *x : true;
840 }
841 
842 template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) {
843  return bool(x) ? *x > v : false;
844 }
845 
846 template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) {
847  return bool(x) ? v < *x : false;
848 }
849 
850 template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) {
851  return bool(x) ? *x >= v : false;
852 }
853 
854 template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) {
855  return bool(x) ? v <= *x : false;
856 }
857 
858 template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) {
859  return bool(x) ? *x <= v : true;
860 }
861 
862 template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) {
863  return bool(x) ? v >= *x : true;
864 }
865 
866 
867 // 20.5.12, Specialized algorithms
868 
869 template <class T>
870 void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
871  x.swap(y);
872 }
873 
874 template <class T>
875 constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
876  return optional<typename std::decay<T>::type > (constexpr_forward<T>(v));
877 }
878 
879 template <class X>
880 constexpr optional<X&> make_optional(std::reference_wrapper<X> v) {
881  return optional<X&>(v.get());
882 }
883 
884 
886 
888 
889 } // namespace gul14
890 
891 
893 namespace std {
894 template <typename T>
895 struct hash<gul14::optional<T>>
896 {
897  typedef typename hash<T>::result_type result_type;
898  typedef gul14::optional<T> argument_type;
899 
900  constexpr result_type operator()(argument_type const& arg) const {
901  return arg ? std::hash<T>{}(*arg) : result_type{};
902  }
903 };
904 
905 template <typename T>
906 struct hash<gul14::optional<T&>>
907 {
908  typedef typename hash<T>::result_type result_type;
909  typedef gul14::optional<T&> argument_type;
910 
911  constexpr result_type operator()(argument_type const& arg) const {
912  return arg ? std::hash<T>{}(*arg) : result_type{};
913  }
914 };
915 }
917 
918 #undef GUL_OPTIONAL_REQUIRES
919 #undef GUL_OPTIONAL_ASSERTED_EXPRESSION
920 
921 #endif // GUL14_OPTIONAL_H_
A class template that can either contain a value of a certain type or not.
Definition: optional.h:513
A class template that can either contain a value of a certain type or not.
Definition: optional.h:274
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition: SmallVector.h:1656
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
A type for constructor disambiguation, used by gul14::expected, gul14::optional, and gul14::variant.
Definition: utility.h:42
Declaration of the in_place_t family of types and constants and of the monostate type.