23 #include <initializer_list> 25 #include <type_traits> 42 : logic_error{what_arg} {}
52 return static_cast<T&&
>(
t);
59 static_assert(!std::is_lvalue_reference<T>::value,
"!!");
60 return static_cast<T&&
>(
t);
64 inline constexpr std::remove_reference_t<T>&&
67 return static_cast<std::remove_reference_t<T>&&
>(
t);
77 template<
typename X,
size_t S = sizeof(std::declval<X&>().operator&())>
83 constexpr
static bool value = has_overload<T>(
true);
87 std::enable_if_t<!has_overloaded_addressof<T>::value>* =
nullptr>
94 std::enable_if_t<has_overloaded_addressof<T>::value>* =
nullptr>
97 return std::addressof(ref);
124 template<
typename... Args>
139 template<
typename... Args>
166 template<
typename... Args>
172 template<
typename U,
typename... Args,
173 std::enable_if_t<std::is_constructible<
174 T, std::initializer_list<U>>::value>* =
nullptr>
177 : init_(true), storage_(il,
std::forward<Args>(args)...)
183 if (init_) storage_.
value_.T::~T();
197 : init_(true), storage_(v)
206 template<
typename... Args>
212 template<
typename U,
typename... Args,
213 std::enable_if_t<std::is_constructible<
214 T, std::initializer_list<U>>::value>* =
nullptr>
216 std::initializer_list<U> il,
218 : init_(true), storage_(il,
std::forward<Args>(args)...)
227 std::is_trivially_destructible<T>::value,
237 static_assert(!std::is_same<std::decay_t<T>,
nullopt_t>::value,
239 static_assert(!std::is_same<std::decay_t<T>,
in_place_t>::value,
242 constexpr
bool initialized()
const noexcept
246 std::remove_const_t<T>* dataptr()
248 return std::addressof(Base::storage_.value_);
250 constexpr
const T* dataptr()
const 255 constexpr
const T& contained_val()
const&
257 return Base::storage_.value_;
259 constexpr T&& contained_val() &&
261 return std::move(Base::storage_.value_);
263 constexpr T& contained_val() &
265 return Base::storage_.value_;
268 void clear() noexcept
270 if (initialized()) dataptr()->T::~T();
274 template<
typename... Args>
275 void initialize(Args&&... args) noexcept(
276 noexcept(T(std::forward<Args>(args)...)))
278 assert(!Base::init_);
279 ::new (static_cast<void*>(dataptr()))
280 T(std::forward<Args>(args)...);
284 template<
typename U,
typename... Args>
285 void initialize(std::initializer_list<U> il, Args&&... args) noexcept(
286 noexcept(T(il, std::forward<Args>(args)...)))
288 assert(!Base::init_);
289 ::new (static_cast<void*>(dataptr()))
290 T(il, std::forward<Args>(args)...);
302 if (rhs.initialized()) {
303 ::new (static_cast<void*>(dataptr())) T(*rhs);
309 std::is_nothrow_move_constructible<T>::value)
312 if (rhs.initialized()) {
313 ::new (static_cast<void*>(dataptr()))
323 template<
typename... Args>
325 : Base(
in_place_t{}, opt_impl::constexpr_forward<Args>(args)...)
329 template<
typename U,
typename... Args,
330 std::enable_if_t<std::is_constructible<
331 T, std::initializer_list<U>>::value>* =
nullptr>
335 opt_impl::constexpr_forward<Args>(args)...)
349 if (initialized() ==
true && rhs.initialized() ==
false)
351 else if (initialized() ==
false && rhs.initialized() ==
true)
353 else if (initialized() ==
true && rhs.initialized() ==
true)
354 contained_val() = *rhs;
359 std::is_nothrow_move_assignable<T>::value&&
360 std::is_nothrow_move_constructible<T>::value)
362 if (initialized() ==
true && rhs.initialized() ==
false)
364 else if (initialized() ==
false && rhs.initialized() ==
true)
365 initialize(std::move(*rhs));
366 else if (initialized() ==
true && rhs.initialized() ==
true)
367 contained_val() = std::move(*rhs);
373 std::is_same<std::decay_t<U>, T>::value,
optional&>
376 contained_val() = std::forward<U>(v);
378 initialize(std::forward<U>(v));
383 template<
typename... Args>
void emplace(Args&&... args)
386 initialize(std::forward<Args>(args)...);
389 template<
typename U,
typename... Args>
390 void emplace(std::initializer_list<U> il, Args&&... args)
393 initialize<U, Args...>(il, std::forward<Args>(args)...);
397 std::is_nothrow_move_constructible<T>::value&& noexcept(
399 std::declval<T&>())))
401 if (initialized() ==
true && rhs.initialized() ==
false) {
402 rhs.initialize(std::move(**
this));
404 }
else if (initialized() ==
false &&
405 rhs.initialized() ==
true) {
406 initialize(std::move(*rhs));
408 }
else if (initialized() ==
true && rhs.initialized() ==
true) {
414 explicit constexpr
operator bool() const noexcept
416 return initialized();
420 return initialized();
425 assert(initialized());
431 assert(initialized());
437 assert(initialized());
438 return contained_val();
443 assert(initialized());
444 return contained_val();
449 assert(initialized());
455 return initialized() ? contained_val()
457 "bad optional access"),
463 return initialized() ? contained_val()
465 "bad optional access"),
471 if (!initialized()) {
474 return std::move(contained_val());
477 template<
typename V> constexpr T
value_or(V&& v)
const&
479 return *
this ? **this
480 : opt_impl::convert<T>(
481 opt_impl::constexpr_forward<V>(v));
484 template<
typename V> constexpr T
value_or(V&& v) &&
489 : opt_impl::convert<T>(
490 opt_impl::constexpr_forward<V>(v));
498 static_assert(
sizeof(T) == 0,
"optional references disallowed");
505 return bool(x) != bool(y) ? false : bool(x) ==
false ? true : *x == *y;
515 constexpr
bool operator<(const optional<T>& x,
const optional<T>& y)
517 return (!y) ? false : (!x) ?
true : *x < *y;
527 constexpr
bool operator<=(const optional<T>& x,
const optional<T>& y)
564 constexpr
bool operator<(const optional<T>&,
nullopt_t) noexcept
570 constexpr
bool operator<(nullopt_t, const optional<T>& x) noexcept
576 constexpr
bool operator<=(const optional<T>& x,
nullopt_t) noexcept
582 constexpr
bool operator<=(nullopt_t, const optional<T>&) noexcept
614 return bool(x) ? *x == v :
false;
619 return bool(x) ? v == *x :
false;
624 return bool(x) ? *x != v :
true;
629 return bool(x) ? v != *x :
true;
632 template<
typename T> constexpr
bool operator<(const optional<T>& x,
const T& v)
634 return bool(x) ? *x < v :
true;
639 return bool(x) ? v > *x :
true;
644 return bool(x) ? *x > v :
false;
647 template<
typename T> constexpr
bool operator<(const T& v, const optional<T>& x)
649 return bool(x) ? v < *x :
false;
654 return bool(x) ? *x >= v :
false;
657 template<
typename T> constexpr
bool operator<=(const T& v, const optional<T>& x)
659 return bool(x) ? v <= *x :
false;
662 template<
typename T> constexpr
bool operator<=(const optional<T>& x,
const T& v)
664 return bool(x) ? *x <= v :
true;
669 return bool(x) ? v >= *x :
true;
676 return bool(x) ? *x == v :
false;
682 return bool(x) ? v == *x :
false;
688 return bool(x) ? *x != v :
true;
694 return bool(x) ? v != *x :
true;
697 template<
typename T> constexpr
bool operator<(const optional<T&>& x,
const T& v)
699 return bool(x) ? *x < v :
true;
704 return bool(x) ? v > *x :
true;
709 return bool(x) ? *x > v :
false;
712 template<
typename T> constexpr
bool operator<(const T& v, const optional<T&>& x)
714 return bool(x) ? v < *x :
false;
720 return bool(x) ? *x >= v :
false;
724 constexpr
bool operator<=(const T& v, const optional<T&>& x)
726 return bool(x) ? v <= *x :
false;
730 constexpr
bool operator<=(const optional<T&>& x,
const T& v)
732 return bool(x) ? *x <= v :
true;
738 return bool(x) ? v >= *x :
true;
745 return bool(x) ? *x == v :
false;
751 return bool(x) ? v == *x :
false;
757 return bool(x) ? *x != v :
true;
763 return bool(x) ? v != *x :
true;
767 constexpr
bool operator<(const optional<const T&>& x,
const T& v)
769 return bool(x) ? *x < v :
true;
775 return bool(x) ? v > *x :
true;
781 return bool(x) ? *x > v :
false;
785 constexpr
bool operator<(const T& v, const optional<const T&>& x)
787 return bool(x) ? v < *x :
false;
793 return bool(x) ? *x >= v :
false;
797 constexpr
bool operator<=(const T& v, const optional<const T&>& x)
799 return bool(x) ? v <= *x :
false;
803 constexpr
bool operator<=(const optional<const T&>& x,
const T& v)
805 return bool(x) ? *x <= v :
true;
811 return bool(x) ? v >= *x :
true;
825 opt_impl::constexpr_forward<T>(v));
constexpr result_type operator()(const argument_type &arg) const
constexpr T && value() &&
optional & operator=(const optional &rhs)
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
std::conditional_t< std::is_trivially_destructible< T >::value, constexpr_optional_base< std::remove_const_t< T > >, optional_base< std::remove_const_t< T > >> OptionalBase
constexpr constexpr_optional_base(const T &v)
static constexpr bool has_overload(bool)
constexpr constexpr_storage_t(Args &&... args)
constexpr constexpr_optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
constexpr bool operator==(const optional< T > &x, const optional< T > &y)
constexpr optional(in_place_t, Args &&... args)
constexpr constexpr_optional_base(in_place_t, Args &&... args)
constexpr T * operator->()
constexpr constexpr_optional_base() noexcept
constexpr optional() noexcept
constexpr struct in_place_t in_place
constexpr optional(T &&v)
constexpr_storage_t< T > storage_
constexpr T value_or(V &&v) &&
bad_optional_access(const char *what_arg)
constexpr optional< std::decay_t< T > > make_optional(T &&v)
constexpr result_type operator()(const argument_type &arg) const
constexpr T && constexpr_forward(std::remove_reference_t< T > &&t) noexcept
optional & operator=(optional &&rhs) noexcept(std::is_nothrow_move_assignable< T >::value &&std::is_nothrow_move_constructible< T >::value)
constexpr optional_base(T &&v)
constexpr T value_or(V &&v) const &
void emplace(Args &&... args)
constexpr const T & value() const &
optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
optional & operator=(nullopt_t) noexcept
constexpr bool operator!=(const optional< T > &x, const optional< T > &y)
constexpr std::remove_reference_t< T > && constexpr_move(T &&t) noexcept
constexpr optional(const T &v)
constexpr T && operator*() &&
constexpr storage_t(trivial_init_t) noexcept
constexpr const T & operator*() const &
void adl_swap(T &t, T &u) noexcept(noexcept(swap(t, u)))
void emplace(std::initializer_list< U > il, Args &&... args)
typename hash< T >::result_type result_type
constexpr storage_t(Args &&... args)
constexpr bool operator>(const optional< T > &x, const optional< T > &y)
constexpr T * static_addressof(T &ref)
T * static_addressof(T &ref)
void swap(optional< T > &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&noexcept(opt_impl::swap_ns::adl_swap(std::declval< T &>(), std::declval< T &>())))
constexpr const T * operator->() const
constexpr constexpr_storage_t(trivial_init_t) noexcept
optional_base(in_place_t, Args &&... args)
constexpr optional_base(const T &v)
constexpr nullopt_t nullopt
constexpr bool has_value() const noexcept
constexpr constexpr_optional_base(T &&v)
static constexpr bool has_overload(...)
auto operator=(U &&v) -> std::enable_if_t< std::is_same< std::decay_t< U >, T >::value, optional &>
optional(const optional &rhs)
constexpr bool operator>=(const optional< T > &x, const optional< T > &y)
constexpr optional_base() noexcept
constexpr struct opt_impl::trivial_init_t trivial_init
typename hash< T >::result_type result_type
constexpr optional(in_place_t, std::initializer_list< U > il, Args &&... args)
std::array< GLint, 4 > value_type
constexpr optional(nullopt_t) noexcept
constexpr T & operator*() &
constexpr nullopt_t(init)
optional(optional &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)