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