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