10 # ifndef ___OPTIONAL_HPP___ 11 # define ___OPTIONAL_HPP___ 14 # include <type_traits> 15 # include <initializer_list> 17 # include <functional> 19 # include "athena/Global.hpp" 21 # define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false 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___ 27 # define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 30 # if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) 31 # define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 33 # define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 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___ 41 # define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 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_ 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_ 59 # if (_MSC_VER >= 1900) 60 # define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 64 # if defined __clang__ 65 # if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) 66 # define OPTIONAL_HAS_THIS_RVALUE_REFS 1 68 # define OPTIONAL_HAS_THIS_RVALUE_REFS 0 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 75 # define OPTIONAL_HAS_THIS_RVALUE_REFS 0 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 83 # define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 84 # define OPTIONAL_CONSTEXPR_INIT_LIST 87 # if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) 88 # define OPTIONAL_HAS_MOVE_ACCESSORS 1 90 # define OPTIONAL_HAS_MOVE_ACCESSORS 0 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 97 # define OPTIONAL_MUTABLE_CONSTEXPR constexpr 102 namespace experimental{
105 # if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 107 # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 109 # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 111 # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 114 template <
typename T>
115 using is_trivially_destructible = std::has_trivial_destructor<T>;
119 # if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) 121 # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 123 # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 125 # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 134 constexpr
static bool value = std::is_nothrow_constructible<T, T&&>::value;
138 template <
class T,
class U>
141 template <
class X,
class Y>
142 constexpr
static bool has_assign(...) {
return false; }
144 template <
class X,
class Y,
size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
146 constexpr
static bool has_assign(
bool) {
return true; }
148 constexpr
static bool value = has_assign<T, U>(
true);
155 template <
class X,
bool has_any_move_assign>
157 constexpr
static bool value =
false;
162 constexpr
static bool value = noexcept( std::declval<X&>() = std::declval<X&&>() );
178 template <
class T>
class optional<T&>;
182 template <
class T>
inline constexpr T&& constexpr_forward(
typename std::remove_reference<T>::type& t) noexcept
184 return static_cast<T&&
>(t);
187 template <
class T>
inline constexpr T&& constexpr_forward(
typename std::remove_reference<T>::type&& t) noexcept
189 static_assert(!std::is_lvalue_reference<T>::value,
"!!");
190 return static_cast<T&&
>(t);
193 template <
class T>
inline constexpr
typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
195 return static_cast<typename std::remove_reference<T>::type&&
>(t);
200 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) 202 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) 210 template <
typename T>
214 constexpr
static bool has_overload(...) {
return false; }
216 template <
class X,
size_t S = sizeof(std::declval<X&>().operator&()) >
217 constexpr
static bool has_overload(
bool) {
return true; }
219 constexpr
static bool value = has_overload<T>(
true);
222 template <
typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
223 constexpr T* static_addressof(T& ref)
228 template <
typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
229 T* static_addressof(T& ref)
231 return std::addressof(ref);
237 U convert(U v) {
return v; }
269 unsigned char dummy_;
274 template <
class... Args>
275 constexpr
storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
284 unsigned char dummy_;
289 template <
class... Args>
290 constexpr
constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
292 ~constexpr_storage_t() =
default;
302 constexpr
optional_base() noexcept : init_(
false), storage_(trivial_init) {};
304 explicit constexpr
optional_base(
const T& v) : init_(
true), storage_(v) {}
306 explicit constexpr optional_base(T&& v) : init_(
true), storage_(constexpr_move(v)) {}
308 template <
class... Args>
explicit optional_base(
in_place_t, Args&&... args)
309 : init_(
true), storage_(constexpr_forward<Args>(args)...) {}
311 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
312 explicit optional_base(
in_place_t, std::initializer_list<U> il, Args&&... args)
313 : init_(
true), storage_(il, std::forward<Args>(args)...) {}
315 ~optional_base() {
if (init_) storage_.value_.T::~T(); }
329 explicit constexpr constexpr_optional_base(T&& v) : init_(
true), storage_(constexpr_move(v)) {}
331 template <
class... Args>
explicit constexpr constexpr_optional_base(
in_place_t, Args&&... args)
332 : init_(
true), storage_(constexpr_forward<Args>(args)...) {}
334 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
335 OPTIONAL_CONSTEXPR_INIT_LIST
explicit constexpr_optional_base(
in_place_t, std::initializer_list<U> il, Args&&... args)
336 : init_(
true), storage_(il, std::forward<Args>(args)...) {}
338 ~constexpr_optional_base() =
default;
342 using OptionalBase =
typename std::conditional<
343 is_trivially_destructible<T>::value,
351 class optional :
private OptionalBase<T>
353 static_assert( !std::is_same<
typename std::decay<T>::type,
nullopt_t>::value,
"bad T" );
354 static_assert( !std::is_same<
typename std::decay<T>::type,
in_place_t>::value,
"bad T" );
357 constexpr
bool initialized()
const noexcept {
return OptionalBase<T>::init_; }
358 T* dataptr() {
return std::addressof(OptionalBase<T>::storage_.value_); }
359 constexpr
const T* dataptr()
const {
return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
361 # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 362 constexpr
const T& contained_val()
const& {
return OptionalBase<T>::storage_.value_; }
363 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 364 OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && {
return std::move(OptionalBase<T>::storage_.value_); }
365 OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & {
return OptionalBase<T>::storage_.value_; }
367 T& contained_val() & {
return OptionalBase<T>::storage_.value_; }
368 T&& contained_val() && {
return std::move(OptionalBase<T>::storage_.value_); }
371 constexpr
const T& contained_val()
const {
return OptionalBase<T>::storage_.value_; }
372 T& contained_val() {
return OptionalBase<T>::storage_.value_; }
375 void clear() noexcept {
376 if (initialized()) dataptr()->T::~T();
377 OptionalBase<T>::init_ =
false;
380 template <
class... Args>
381 void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...)))
383 assert(!OptionalBase<T>::init_);
384 ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
385 OptionalBase<T>::init_ =
true;
388 template <
class U,
class... Args>
389 void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...)))
391 assert(!OptionalBase<T>::init_);
392 ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
393 OptionalBase<T>::init_ =
true;
397 typedef T value_type;
400 constexpr
optional() noexcept : OptionalBase<T>() {};
406 if (rhs.initialized()) {
407 ::new (static_cast<void*>(dataptr())) T(*rhs);
408 OptionalBase<T>::init_ =
true;
415 if (rhs.initialized()) {
416 ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
417 OptionalBase<T>::init_ =
true;
421 constexpr
optional(
const T& v) : OptionalBase<T>(v) {}
423 constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
425 template <
class... Args>
426 explicit constexpr optional(
in_place_t, Args&&... args)
427 : OptionalBase<T>(
in_place_t{}, constexpr_forward<Args>(args)...) {}
429 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
430 OPTIONAL_CONSTEXPR_INIT_LIST
explicit optional(
in_place_t, std::initializer_list<U> il, Args&&... args)
431 : OptionalBase<T>(
in_place_t{}, il, constexpr_forward<Args>(args)...) {}
434 ~optional() =
default;
443 optional& operator=(
const optional& rhs)
445 if (initialized() ==
true && rhs.initialized() ==
false) clear();
446 else if (initialized() ==
false && rhs.initialized() ==
true) initialize(*rhs);
447 else if (initialized() ==
true && rhs.initialized() ==
true) contained_val() = *rhs;
451 optional& operator=(optional&& rhs)
454 if (initialized() ==
true && rhs.initialized() ==
false) clear();
455 else if (initialized() ==
false && rhs.initialized() ==
true) initialize(std::move(*rhs));
456 else if (initialized() ==
true && rhs.initialized() ==
true) contained_val() = std::move(*rhs);
461 auto operator=(U&& v)
462 ->
typename enable_if
464 is_same<typename decay<U>::type, T>::value,
468 if (initialized()) { contained_val() = std::forward<U>(v); }
469 else { initialize(std::forward<U>(v)); }
474 template <
class... Args>
475 void emplace(Args&&... args)
478 initialize(std::forward<Args>(args)...);
481 template <
class U,
class... Args>
482 void emplace(initializer_list<U> il, Args&&... args)
485 initialize<U, Args...>(il, std::forward<Args>(args)...);
491 if (initialized() ==
true && rhs.initialized() ==
false) { rhs.initialize(std::move(**
this)); clear(); }
492 else if (initialized() ==
false && rhs.initialized() ==
true) { initialize(std::move(*rhs)); rhs.clear(); }
493 else if (initialized() ==
true && rhs.initialized() ==
true) {
using std::swap; swap(**
this, *rhs); }
498 explicit constexpr
operator bool()
const noexcept {
return initialized(); }
500 constexpr T
const* operator ->()
const {
501 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
504 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 506 OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
507 assert (initialized());
511 constexpr T
const& operator *()
const& {
512 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
515 OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
516 assert (initialized());
517 return contained_val();
520 OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
521 assert (initialized());
522 return constexpr_move(contained_val());
525 constexpr T
const& value()
const& {
526 if (!initialized()) atFatal(
"bad optional access");
527 return contained_val();
530 OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
531 if (!initialized()) atFatal(
"bad optional access");
532 return contained_val();
535 OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
536 if (!initialized()) atFatal(
"bad optional access");
537 return std::move(contained_val());
543 assert (initialized());
547 constexpr T
const& operator *()
const {
548 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
552 assert (initialized());
553 return contained_val();
556 constexpr T
const& value()
const {
558 atFatal(
"bad optional access");
559 return contained_val();
564 atFatal(
"bad optional access");
565 return contained_val();
570 # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 573 constexpr T value_or(V&& v)
const&
575 return *
this ? **
this : detail_::convert<T>(constexpr_forward<V>(v));
578 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1 581 OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
583 return *
this ? constexpr_move(
const_cast<optional<T>&
>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
591 return *
this ? constexpr_move(
const_cast<optional<T>&
>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
599 constexpr T value_or(V&& v)
const 601 return *
this ? **
this : detail_::convert<T>(constexpr_forward<V>(v));
612 static_assert( !std::is_same<T, nullopt_t>::value,
"bad T" );
613 static_assert( !std::is_same<T, in_place_t>::value,
"bad T" );
619 constexpr
optional() noexcept : ref(
nullptr) {}
623 constexpr
optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
629 explicit constexpr
optional(
in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
651 template <
typename U>
652 auto operator=(U&& rhs) noexcept
653 ->
typename enable_if
663 template <
typename U>
664 auto operator=(U&& rhs) noexcept
665 ->
typename enable_if
672 void emplace(T& v) noexcept {
673 ref = detail_::static_addressof(v);
676 void emplace(T&&) =
delete;
681 std::swap(ref, rhs.ref);
685 constexpr T* operator->()
const {
686 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
689 constexpr T& operator*()
const {
690 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
693 constexpr T& value()
const {
694 if (!ref) atFatal(
"bad optional access");
698 explicit constexpr
operator bool()
const noexcept {
699 return ref !=
nullptr;
703 constexpr
typename decay<T>::type value_or(V&& v)
const 705 return *
this ? **
this : detail_::convert<typename decay<T>::type>(constexpr_forward<V>(v));
713 static_assert(
sizeof(T) == 0,
"optional rvalue references disallowed" );
720 return bool(x) != bool(y) ?
false : bool(x) ==
false ?
true : *x == *y;
728 template <
class T> constexpr
bool operator<(const optional<T>& x,
const optional<T>& y)
730 return (!y) ?
false : (!x) ?
true : *x < *y;
738 template <
class T> constexpr
bool operator<=(const optional<T>& x,
const optional<T>& y)
770 template <
class T> constexpr
bool operator<(const optional<T>&,
nullopt_t) noexcept
775 template <
class T> constexpr
bool operator<(nullopt_t, const optional<T>& x) noexcept
780 template <
class T> constexpr
bool operator<=(const optional<T>& x,
nullopt_t) noexcept
785 template <
class T> constexpr
bool operator<=(nullopt_t, const optional<T>&) noexcept
813 template <
class T> constexpr
bool operator==(
const optional<T>& x,
const T& v)
815 return bool(x) ? *x == v :
false;
818 template <
class T> constexpr
bool operator==(
const T& v,
const optional<T>& x)
820 return bool(x) ? v == *x :
false;
823 template <
class T> constexpr
bool operator!=(
const optional<T>& x,
const T& v)
825 return bool(x) ? *x != v :
true;
828 template <
class T> constexpr
bool operator!=(
const T& v,
const optional<T>& x)
830 return bool(x) ? v != *x :
true;
833 template <
class T> constexpr
bool operator<(const optional<T>& x,
const T& v)
835 return bool(x) ? *x < v :
true;
838 template <
class T> constexpr
bool operator>(
const T& v,
const optional<T>& x)
840 return bool(x) ? v > *x :
true;
843 template <
class T> constexpr
bool operator>(
const optional<T>& x,
const T& v)
845 return bool(x) ? *x > v :
false;
848 template <
class T> constexpr
bool operator<(const T& v, const optional<T>& x)
850 return bool(x) ? v < *x :
false;
853 template <
class T> constexpr
bool operator>=(
const optional<T>& x,
const T& v)
855 return bool(x) ? *x >= v :
false;
858 template <
class T> constexpr
bool operator<=(const T& v, const optional<T>& x)
860 return bool(x) ? v <= *x :
false;
863 template <
class T> constexpr
bool operator<=(const optional<T>& x,
const T& v)
865 return bool(x) ? *x <= v :
true;
868 template <
class T> constexpr
bool operator>=(
const T& v,
const optional<T>& x)
870 return bool(x) ? v >= *x :
true;
875 template <
class T> constexpr
bool operator==(
const optional<T&>& x,
const T& v)
877 return bool(x) ? *x == v :
false;
880 template <
class T> constexpr
bool operator==(
const T& v,
const optional<T&>& x)
882 return bool(x) ? v == *x :
false;
885 template <
class T> constexpr
bool operator!=(
const optional<T&>& x,
const T& v)
887 return bool(x) ? *x != v :
true;
890 template <
class T> constexpr
bool operator!=(
const T& v,
const optional<T&>& x)
892 return bool(x) ? v != *x :
true;
895 template <
class T> constexpr
bool operator<(const optional<T&>& x,
const T& v)
897 return bool(x) ? *x < v :
true;
900 template <
class T> constexpr
bool operator>(
const T& v,
const optional<T&>& x)
902 return bool(x) ? v > *x :
true;
905 template <
class T> constexpr
bool operator>(
const optional<T&>& x,
const T& v)
907 return bool(x) ? *x > v :
false;
910 template <
class T> constexpr
bool operator<(const T& v, const optional<T&>& x)
912 return bool(x) ? v < *x :
false;
915 template <
class T> constexpr
bool operator>=(
const optional<T&>& x,
const T& v)
917 return bool(x) ? *x >= v :
false;
920 template <
class T> constexpr
bool operator<=(const T& v, const optional<T&>& x)
922 return bool(x) ? v <= *x :
false;
925 template <
class T> constexpr
bool operator<=(const optional<T&>& x,
const T& v)
927 return bool(x) ? *x <= v :
true;
930 template <
class T> constexpr
bool operator>=(
const T& v,
const optional<T&>& x)
932 return bool(x) ? v >= *x :
true;
938 return bool(x) ? *x == v :
false;
943 return bool(x) ? v == *x :
false;
948 return bool(x) ? *x != v :
true;
953 return bool(x) ? v != *x :
true;
956 template <
class T> constexpr
bool operator<(const optional<const T&>& x,
const T& v)
958 return bool(x) ? *x < v :
true;
963 return bool(x) ? v > *x :
true;
968 return bool(x) ? *x > v :
false;
971 template <
class T> constexpr
bool operator<(const T& v, const optional<const T&>& x)
973 return bool(x) ? v < *x :
false;
978 return bool(x) ? *x >= v :
false;
981 template <
class T> constexpr
bool operator<=(const T& v, const optional<const T&>& x)
983 return bool(x) ? v <= *x :
false;
986 template <
class T> constexpr
bool operator<=(const optional<const T&>& x,
const T& v)
988 return bool(x) ? *x <= v :
true;
993 return bool(x) ? v >= *x :
true;
1012 constexpr
optional<X&> make_optional(reference_wrapper<X> v)
1023 template <
typename T>
1026 typedef typename hash<T>::result_type result_type;
1029 constexpr result_type operator()(argument_type
const& arg)
const {
1030 return arg ? std::hash<T>{}(*arg) : result_type{};
1034 template <
typename T>
1037 typedef typename hash<T>::result_type result_type;
1040 constexpr result_type operator()(argument_type
const& arg)
const {
1041 return arg ? std::hash<T>{}(*arg) : result_type{};
1046 # undef TR2_OPTIONAL_REQUIRES 1047 # undef TR2_OPTIONAL_ASSERTED_EXPRESSION 1049 # endif //___OPTIONAL_HPP___ Definition: optional.hpp:267
Definition: optional.hpp:282
Definition: optional.hpp:250
Definition: optional.hpp:156
Definition: optional.hpp:100
Definition: optional.hpp:252
Definition: optional.hpp:211
Definition: optional.hpp:139
Definition: optional.hpp:246
Definition: optional.hpp:320
Definition: optional.hpp:153
Definition: optional.hpp:242
Definition: optional.hpp:297
Definition: optional.hpp:259
Definition: optional.hpp:175
Definition: optional.hpp:132
Definition: optional.hpp:610