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