14#ifndef RANGES_V3_UTILITY_OPTIONAL_HPP
15#define RANGES_V3_UTILITY_OPTIONAL_HPP
18#include <initializer_list>
24#include <range/v3/detail/config.hpp>
25#include <range/v3/utility/addressof.hpp>
27#include <range/v3/utility/static_const.hpp>
30#include <range/v3/detail/prologue.hpp>
39 virtual const char * what()
const noexcept override
41 return "bad optional access";
52#if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
53 inline constexpr nullopt_t nullopt{nullopt_t::tag{}};
61 static constexpr nullopt_t nullopt{nullopt_t::tag{}};
64 constexpr nullopt_t nullopt_holder<T>::nullopt;
69 constexpr auto & nullopt = detail::nullopt_holder<void>::nullopt;
76 template<
typename =
void>
77 [[noreturn]]
bool throw_bad_optional_access()
79 throw bad_optional_access{};
82 namespace optional_adl
84 template<typename T, bool = std::is_trivially_destructible<T>::value>
85 struct optional_storage
94 constexpr optional_storage() noexcept
98 detail::is_trivially_copyable_v<T>>{})
100 template(
typename... Args)(
101 requires constructible_from<T, Args...>)
102 constexpr explicit optional_storage(in_place_t,
104 noexcept(std::is_nothrow_constructible<T, Args...>::value)
105 : data_(static_cast<Args &&>(args)...)
109 constexpr void reset() noexcept
117 constexpr optional_storage(tag, std::false_type) noexcept
121 constexpr optional_storage(tag, std::true_type) noexcept
128 struct optional_storage<T, false>
141 constexpr optional_storage() noexcept
145 template(
typename... Args)(
146 requires constructible_from<T, Args...>)
147 constexpr explicit optional_storage(in_place_t,
149 noexcept(std::is_nothrow_constructible<T, Args...>::value)
150 : data_(static_cast<Args &&>(args)...)
153 optional_storage(optional_storage
const &) =
default;
154 optional_storage(optional_storage &&) =
default;
155 optional_storage & operator=(optional_storage
const &) =
default;
156 optional_storage & operator=(optional_storage &&) =
default;
158 void reset() noexcept
169 struct optional_base :
private optional_storage<T>
171 using optional_storage<T>::optional_storage;
172 using optional_storage<T>::reset;
174 constexpr bool has_value() const noexcept
180 return RANGES_EXPECT(engaged_), data_;
182 constexpr T
const &
operator*() const & noexcept
184 return RANGES_EXPECT(engaged_), data_;
188 return RANGES_EXPECT(engaged_), detail::move(data_);
190 constexpr T
const &&
operator*() const && noexcept
192 return RANGES_EXPECT(engaged_), detail::move(data_);
194 constexpr T * operator->() noexcept
196 return RANGES_EXPECT(engaged_), detail::addressof(data_);
198 constexpr T
const * operator->() const noexcept
200 return RANGES_EXPECT(engaged_), detail::addressof(data_);
203 constexpr auto swap(optional_base & that)
204 noexcept(std::is_nothrow_move_constructible<T>::value &&
205 is_nothrow_swappable<T>::value)
207 requires move_constructible<T> && swappable<T>)
209 constexpr bool can_swap_trivially =
210 !::concepts::adl_swap_detail::is_adl_swappable_v<T> &&
211 detail::is_trivially_move_constructible_v<T> &&
212 detail::is_trivially_move_assignable_v<T>;
218 template(
typename... Args)(
219 requires constructible_from<T, Args...>)
220 T & construct_from(Args &&... args)
221 noexcept(std::is_nothrow_constructible<T, Args...>::value)
223 RANGES_EXPECT(!engaged_);
224 auto const address =
static_cast<void *
>(std::addressof(data_));
225 ::new(address) T(
static_cast<Args &&
>(args)...);
229 template(
typename I)(
230 requires constructible_from<T,
decltype(*std::declval<const I &>())>)
231 T & construct_from_deref(
const I & it)
233 RANGES_EXPECT(!engaged_);
234 auto const address =
static_cast<void *
>(std::addressof(data_));
235 ::new(address) T(*it);
240 constexpr void assign_from(U && that)
noexcept(
241 std::is_nothrow_constructible<T, decltype(*static_cast<U &&>(that))>::
242 value && std::is_nothrow_assignable<
243 T &, decltype(*static_cast<U &&>(that))>::value)
245 if(!that.has_value())
248 data_ = *
static_cast<U &&
>(that);
252 static_cast<void *
>(detail::addressof(data_));
253 ::new(address) T(*
static_cast<U &&
>(that));
259 constexpr void swap_(std::true_type, optional_base & that)
noexcept
261 ranges::swap(
static_cast<optional_storage<T> &
>(*
this),
262 static_cast<optional_storage<T> &
>(that));
264 constexpr void swap_(std::false_type, optional_base & that)
noexcept(
265 std::is_nothrow_move_constructible<T>::value &&
266 is_nothrow_swappable<T>::value)
268 if(that.engaged_ == engaged_)
271 ranges::swap(data_, that.data_);
275 auto & src = engaged_ ? *this : that;
276 auto & dst = engaged_ ? that : *
this;
277 dst.construct_from(detail::move(src.data_));
282 using optional_storage<T>::engaged_;
283 using optional_storage<T>::data_;
287 struct optional_base<T &>
289 optional_base() =
default;
290 template(
typename Arg)(
291 requires constructible_from<T &, Arg>)
292 constexpr explicit optional_base(in_place_t, Arg && arg)
noexcept
293 : ptr_(detail::addressof(arg))
295 constexpr bool has_value() const noexcept
301 return RANGES_EXPECT(ptr_), *ptr_;
303 constexpr T * operator->() const noexcept
305 return RANGES_EXPECT(ptr_), ptr_;
307 constexpr void reset() noexcept
312 constexpr auto swap(optional_base & that)
313 noexcept(is_nothrow_swappable<T>::value)
315 requires swappable<T>)
317 if(ptr_ && that.ptr_)
318 ranges::swap(*ptr_, *that.ptr_);
320 ranges::swap(ptr_, that.ptr_);
324 template(
typename U)(
325 requires convertible_to<U &, T &>)
326 constexpr T & construct_from(U && ref)
noexcept
328 RANGES_EXPECT(!ptr_);
329 ptr_ = detail::addressof(ref);
333 constexpr void assign_from(U && that)
335 if(ptr_ && that.ptr_)
346 struct optional_copy : optional_base<T>
348 optional_copy() =
default;
349 optional_copy(optional_copy
const & that)
noexcept(
350 std::is_nothrow_copy_constructible<T>::value)
353 this->construct_from(*that);
355 optional_copy(optional_copy &&) =
default;
356 optional_copy & operator=(optional_copy
const &) =
default;
357 optional_copy & operator=(optional_copy &&) =
default;
359 using optional_base<T>::optional_base;
363 using copy_construct_layer =
364 meta::if_c<std::is_copy_constructible<T>::value &&
365 !detail::is_trivially_copy_constructible_v<T>,
366 optional_copy<T>, optional_base<T>>;
369 struct optional_move : copy_construct_layer<T>
371 optional_move() =
default;
372 optional_move(optional_move
const &) =
default;
373 optional_move(optional_move && that)
noexcept(
374 std::is_nothrow_move_constructible<T>::value)
377 this->construct_from(std::move(*that));
379 optional_move & operator=(optional_move
const &) =
default;
380 optional_move & operator=(optional_move &&) =
default;
382 using copy_construct_layer<T>::copy_construct_layer;
386 using move_construct_layer =
387 meta::if_c<std::is_move_constructible<T>::value &&
388 !detail::is_trivially_move_constructible_v<T>,
389 optional_move<T>, copy_construct_layer<T>>;
392 struct optional_copy_assign : move_construct_layer<T>
394 optional_copy_assign() =
default;
395 optional_copy_assign(optional_copy_assign
const &) =
default;
396 optional_copy_assign(optional_copy_assign &&) =
default;
397 optional_copy_assign & operator=(optional_copy_assign
const & that)
398 noexcept(std::is_nothrow_copy_constructible<T>::value &&
399 std::is_nothrow_copy_assignable<T>::value)
401 this->assign_from(that);
404 optional_copy_assign & operator=(optional_copy_assign &&) =
default;
406 using move_construct_layer<T>::move_construct_layer;
410 struct deleted_copy_assign : move_construct_layer<T>
412 deleted_copy_assign() =
default;
413 deleted_copy_assign(deleted_copy_assign
const &) =
default;
414 deleted_copy_assign(deleted_copy_assign &&) =
default;
415 deleted_copy_assign & operator=(deleted_copy_assign
const &) =
delete;
416 deleted_copy_assign & operator=(deleted_copy_assign &&) =
default;
418 using move_construct_layer<T>::move_construct_layer;
422 using copy_assign_layer = meta::if_c<
423 std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
424 meta::if_c<std::is_reference<T>::value ||
425 !(detail::is_trivially_copy_constructible_v<T> &&
426 detail::is_trivially_copy_assignable_v<T>),
427 optional_copy_assign<T>, move_construct_layer<T>>,
428 deleted_copy_assign<T>>;
431 struct optional_move_assign : copy_assign_layer<T>
433 optional_move_assign() =
default;
434 optional_move_assign(optional_move_assign
const &) =
default;
435 optional_move_assign(optional_move_assign &&) =
default;
436 optional_move_assign & operator=(optional_move_assign
const &) =
default;
437 optional_move_assign & operator=(optional_move_assign && that)
noexcept(
438 std::is_nothrow_move_constructible<T>::value &&
439 std::is_nothrow_move_assignable<T>::value)
441 this->assign_from(std::move(that));
445 using copy_assign_layer<T>::copy_assign_layer;
449 struct deleted_move_assign : copy_assign_layer<T>
451 deleted_move_assign() =
default;
452 deleted_move_assign(deleted_move_assign
const &) =
default;
453 deleted_move_assign(deleted_move_assign &&) =
default;
454 deleted_move_assign & operator=(deleted_move_assign
const &) =
default;
455 deleted_move_assign & operator=(deleted_move_assign &&) =
delete;
457 using copy_assign_layer<T>::copy_assign_layer;
461 using move_assign_layer = meta::if_c<
462 std::is_move_constructible<T>::value && std::is_move_assignable<T>::value,
463 meta::if_c<std::is_reference<T>::value ||
464 !(detail::is_trivially_move_constructible_v<T> &&
465 detail::is_trivially_move_assignable_v<T>),
466 optional_move_assign<T>, copy_assign_layer<T>>,
467 deleted_move_assign<T>>;
475 template<
typename U,
typename T>
476 CPP_concept optional_should_convert =
478 constructible_from<T, optional<U> & > ||
479 constructible_from<T, optional<U> && > ||
480 constructible_from<T, optional<U>
const & > ||
481 constructible_from<T, optional<U>
const &&> ||
482 convertible_to<optional<U> &, T> ||
483 convertible_to<optional<U> &&, T> ||
484 convertible_to<optional<U>
const &, T> ||
485 convertible_to<optional<U>
const &&, T>
490 template<
typename U,
typename T>
491 CPP_concept optional_should_convert_assign =
492 optional_should_convert<U, T> &&
493 !(assignable_from<T &, optional<U> &> ||
494 assignable_from<T &, optional<U> &&> ||
495 assignable_from<T &, optional<U>
const &> ||
496 assignable_from<T &, optional<U>
const &&>);
500 struct optional : detail::optional_adl::move_assign_layer<T>
503 using base_t = detail::optional_adl::move_assign_layer<T>;
506 CPP_assert(destructible<T>);
507 static_assert(std::is_object<T>::value || std::is_lvalue_reference<T>::value,
"");
508 static_assert((bool)!same_as<
nullopt_t, uncvref_t<T>>,
"");
509 static_assert((bool)!same_as<
in_place_t, uncvref_t<T>>,
"");
520 using base_t::base_t;
522 template(
typename E,
typename... Args)(
523 requires constructible_from<T, std::initializer_list<E> &, Args...>)
526 noexcept(std::is_nothrow_constructible<T, std::initializer_list<E> &,
528 : base_t(in_place, il,
static_cast<Args &&
>(args)...)
531#if defined(__cpp_conditional_explicit) && __cpp_conditional_explicit > 0
532 template(
typename U = T)(
533 requires (!same_as<detail::decay_t<U>,
in_place_t>) AND
534 (!same_as<detail::decay_t<U>,
optional>) AND
535 constructible_from<T, U>)
536 constexpr explicit(!convertible_to<U, T>)
optional(U && v)
537 : base_t(in_place,
static_cast<U &&
>(v))
540 template(
typename U)(
542 constructible_from<T, U const &>)
546 base_t::construct_from(*that);
549 template(
typename U = T)(
550 requires (!same_as<detail::decay_t<U>,
in_place_t>) AND
551 (!same_as<detail::decay_t<U>,
optional>) AND
552 constructible_from<T, U> AND
553 convertible_to<U, T>)
555 : base_t(in_place,
static_cast<U &&
>(v))
557 template(
typename U = T)(
558 requires (!same_as<detail::decay_t<U>,
in_place_t>) AND
559 (!same_as<detail::decay_t<U>,
optional>) AND
560 constructible_from<T, U> AND
561 (!convertible_to<U, T>))
563 : base_t(in_place,
static_cast<U &&
>(v))
566 template(
typename U)(
568 constructible_from<T, U const &> AND
569 convertible_to<U const &, T>)
573 base_t::construct_from(*that);
575 template(
typename U)(
577 constructible_from<T, U const &> AND
578 (!convertible_to<U const &, T>))
582 base_t::construct_from(*that);
586 template(
typename U)(
588 convertible_to<U, T>)
592 base_t::construct_from(detail::move(*that));
594 template(
typename U)(
596 (!convertible_to<U, T>))
600 base_t::construct_from(detail::move(*that));
612 template(
typename U = T)(
613 requires (!same_as<
optional, detail::decay_t<U>>) AND
614 (!(satisfies<T, std::is_scalar> && same_as<T, detail::decay_t<U>>)) AND
615 constructible_from<T, U> AND
616 assignable_from<T &, U>)
617 constexpr optional &
operator=(U && u)
noexcept(
618 std::is_nothrow_constructible<T, U>::value &&
619 std::is_nothrow_assignable<T &, U>::value)
622 **
this =
static_cast<U &&
>(u);
624 base_t::construct_from(
static_cast<U &&
>(u));
628 template(
typename U)(
630 constructible_from<T, const U &> AND
631 assignable_from<T &, const U &>)
634 base_t::assign_from(that);
638 template(
typename U)(
640 constructible_from<T, U> AND
641 assignable_from<T &, U>)
644 base_t::assign_from(std::move(that));
648 template(
typename I)(
649 requires constructible_from<T,
decltype(*std::declval<const I &>())>)
650 T & emplace_deref(
const I & it)
653 return base_t::construct_from_deref(it);
656 template(
typename... Args)(
657 requires constructible_from<T, Args...>)
658 T & emplace(Args &&... args)
noexcept(
659 std::is_nothrow_constructible<T, Args...>::value)
662 return base_t::construct_from(
static_cast<Args &&
>(args)...);
664 template(
typename E,
typename... Args)(
665 requires constructible_from<T, std::initializer_list<E> &, Args...>)
666 T & emplace(std::initializer_list<E> il, Args &&... args)
noexcept(
667 std::is_nothrow_constructible<T, std::initializer_list<E> &, Args...>::value)
670 return base_t::construct_from(il,
static_cast<Args &&
>(args)...);
674 using base_t::operator->;
675 using base_t::operator*;
677 constexpr explicit operator bool()
const noexcept
681 using base_t::has_value;
683 constexpr T
const & value()
const &
685 return (has_value() || detail::throw_bad_optional_access()), **
this;
687 constexpr T & value() &
689 return (has_value() || detail::throw_bad_optional_access()), **
this;
691 constexpr T
const && value()
const &&
693 return (has_value() || detail::throw_bad_optional_access()),
694 detail::move(**
this);
696 constexpr T && value() &&
698 return (has_value() || detail::throw_bad_optional_access()),
699 detail::move(**
this);
702 template(
typename U)(
703 requires copy_constructible<T> AND convertible_to<U, T>)
704 constexpr T value_or(U && u)
const &
706 return has_value() ? **this :
static_cast<T
>((U &&) u);
708 template(
typename U)(
709 requires move_constructible<T> AND convertible_to<U, T>)
710 constexpr T value_or(U && u) &&
712 return has_value() ? detail::move(**
this) :
static_cast<T
>((U &&) u);
721 namespace optional_adl
723 constexpr bool convert_bool(
bool b)
noexcept
729 template<
typename T,
typename U>
730 constexpr auto operator==(optional<T>
const & x, optional<U>
const & y)
731 noexcept(
noexcept(convert_bool(*x == *y)))
732 ->
decltype(convert_bool(*x == *y))
734 return x.has_value() == y.has_value() && (!x || convert_bool(*x == *y));
736 template<
typename T,
typename U>
737 constexpr auto operator!=(optional<T>
const & x, optional<U>
const & y)
738 noexcept(
noexcept(convert_bool(*x != *y)))
739 ->
decltype(convert_bool(*x != *y))
741 return x.has_value() != y.has_value() || (x && convert_bool(*x != *y));
743 template<
typename T,
typename U>
744 constexpr auto operator<(optional<T>
const & x, optional<U>
const & y)
745 noexcept(
noexcept(convert_bool(*x < *y)))
746 ->
decltype(convert_bool(*x < *y))
748 return y && (!x || convert_bool(*x < *y));
750 template<
typename T,
typename U>
751 constexpr auto operator>(optional<T>
const & x, optional<U>
const & y)
752 noexcept(
noexcept(convert_bool(*x > *y)))
753 ->
decltype(convert_bool(*x > *y))
755 return x && (!y || convert_bool(*x > *y));
757 template<
typename T,
typename U>
758 constexpr auto operator<=(optional<T>
const & x, optional<U>
const & y)
759 noexcept(
noexcept(convert_bool(*x <= *y)))
760 ->
decltype(convert_bool(*x <= *y))
762 return !x || (y && convert_bool(*x <= *y));
764 template<
typename T,
typename U>
765 constexpr auto operator>=(optional<T>
const & x, optional<U>
const & y)
766 noexcept(
noexcept(convert_bool(*x >= *y)))
767 ->
decltype(convert_bool(*x >= *y))
769 return !y || (x && convert_bool(*x >= *y));
774 constexpr bool operator==(optional<T>
const & x, nullopt_t)
noexcept
779 constexpr bool operator==(nullopt_t, optional<T>
const & x)
noexcept
784 constexpr bool operator!=(optional<T>
const & x, nullopt_t)
noexcept
789 constexpr bool operator!=(nullopt_t, optional<T>
const & x)
noexcept
794 constexpr bool operator<(optional<T>
const &, nullopt_t)
noexcept
799 constexpr bool operator<(nullopt_t, optional<T>
const & x)
noexcept
804 constexpr bool operator>(optional<T>
const & x, nullopt_t)
noexcept
809 constexpr bool operator>(nullopt_t, optional<T>
const &)
noexcept
814 constexpr bool operator<=(optional<T>
const & x, nullopt_t)
noexcept
819 constexpr bool operator<=(nullopt_t, optional<T>
const &)
noexcept
824 constexpr bool operator>=(optional<T>
const &, nullopt_t)
noexcept
829 constexpr bool operator>=(nullopt_t, optional<T>
const & x)
noexcept
835 template<
typename T,
typename U>
836 constexpr auto operator==(optional<T>
const & x, U
const & y)
837 noexcept(
noexcept(convert_bool(*x == y)))
838 ->
decltype(convert_bool(*x == y))
840 return x && convert_bool(*x == y);
842 template<
typename T,
typename U>
843 constexpr auto operator==(T
const & x, optional<U>
const & y)
844 noexcept(
noexcept(convert_bool(x == *y)))
845 ->
decltype(convert_bool(x == *y))
847 return y && convert_bool(x == *y);
849 template<
typename T,
typename U>
850 constexpr auto operator!=(optional<T>
const & x, U
const & y)
851 noexcept(
noexcept(convert_bool(*x != y)))
852 ->
decltype(convert_bool(*x != y))
854 return !x || convert_bool(*x != y);
856 template<
typename T,
typename U>
857 constexpr auto operator!=(T
const & x, optional<U>
const & y)
858 noexcept(
noexcept(convert_bool(x != *y)))
859 ->
decltype(convert_bool(x != *y))
861 return !y || convert_bool(x != *y);
863 template<
typename T,
typename U>
864 constexpr auto operator<(optional<T>
const & x, U
const & y)
865 noexcept(
noexcept(convert_bool(*x < y)))
866 ->
decltype(convert_bool(*x < y))
868 return !x || convert_bool(*x < y);
870 template<
typename T,
typename U>
871 constexpr auto operator<(T
const & x, optional<U>
const & y)
872 noexcept(
noexcept(convert_bool(x < *y)))
873 ->
decltype(convert_bool(x < *y))
875 return y && convert_bool(x < *y);
877 template<
typename T,
typename U>
878 constexpr auto operator>(optional<T>
const & x, U
const & y)
879 noexcept(
noexcept(convert_bool(*x > y))) ->
decltype(convert_bool(*x > y))
881 return x && convert_bool(*x > y);
883 template<
typename T,
typename U>
884 constexpr auto operator>(T
const & x, optional<U>
const & y)
885 noexcept(
noexcept(convert_bool(x > *y)))
886 ->
decltype(convert_bool(x > *y))
888 return !y || convert_bool(x > *y);
890 template<
typename T,
typename U>
891 constexpr auto operator<=(optional<T>
const & x, U
const & y)
892 noexcept(
noexcept(convert_bool(*x <= y)))
893 ->
decltype(convert_bool(*x <= y))
895 return !x || convert_bool(*x <= y);
897 template<
typename T,
typename U>
898 constexpr auto operator<=(T
const & x, optional<U>
const & y)
899 noexcept(
noexcept(convert_bool(x <= *y)))
900 ->
decltype(convert_bool(x <= *y))
902 return y && convert_bool(x <= *y);
904 template<
typename T,
typename U>
905 constexpr auto operator>=(optional<T>
const & x, U
const & y)
906 noexcept(
noexcept(convert_bool(*x >= y)))
907 ->
decltype(convert_bool(*x >= y))
909 return x && convert_bool(*x >= y);
911 template<
typename T,
typename U>
912 constexpr auto operator>=(T
const & x, optional<U>
const & y)
913 noexcept(
noexcept(convert_bool(x >= *y)))
914 ->
decltype(convert_bool(x >= *y))
916 return !y || convert_bool(x >= *y);
921 auto CPP_auto_fun(swap)(optional<T> &x, optional<T> &y)
932 constexpr auto CPP_auto_fun(make_optional)(T &&t)
934 return optional<detail::decay_t<T>>{
static_cast<T &&
>(t)}
936 template<typename T, typename... Args>
937 constexpr auto CPP_auto_fun(make_optional)(Args &&... args)
939 return optional<T>{in_place,
static_cast<Args &&
>(args)...}
941 template<typename T, typename U, typename... Args>
942 constexpr auto CPP_auto_fun(make_optional)(std::initializer_list<U> il,
945 return optional<T>{in_place, il,
static_cast<Args &&
>(args)...}
952 template<
typename T,
typename Tag =
void,
bool Enable = true>
953 struct non_propagating_cache : optional<T>
955 non_propagating_cache() =
default;
956 constexpr non_propagating_cache(nullopt_t)
noexcept
958 constexpr non_propagating_cache(non_propagating_cache
const &) noexcept
961 constexpr non_propagating_cache(non_propagating_cache && that) noexcept
964 that.optional<T>::reset();
966 constexpr non_propagating_cache & operator=(
967 non_propagating_cache
const &)
noexcept
969 optional<T>::reset();
972 constexpr non_propagating_cache & operator=(
973 non_propagating_cache && that)
noexcept
975 that.optional<T>::reset();
976 optional<T>::reset();
979 using optional<T>::operator=;
981 constexpr T & emplace_deref(
const I & i)
983 return optional<T>::emplace(*i);
987 template<
typename T,
typename Tag>
988 struct non_propagating_cache<T, Tag, false>
994#include <range/v3/detail/epilogue.hpp>
The optional_should_convert_assign concept.
The optional_should_convert concept.
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
Point operator*(double s, const Point &a)
Multiply point by scalar.
Definition shapes.h:250
Definition optional.hpp:38
Definition in_place.hpp:27
Definition optional.hpp:48
Definition optional.hpp:46
Definition optional.hpp:501