8 #ifndef MPARK_VARIANT_HPP
9 #define MPARK_VARIANT_HPP
199 #include <functional>
200 #include <initializer_list>
202 #include <type_traits>
212 #ifndef MPARK_CONFIG_HPP
213 #define MPARK_CONFIG_HPP
216 #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
217 #error "MPark.Variant requires C++11 support."
220 #ifndef __has_attribute
221 #define __has_attribute(x) 0
224 #ifndef __has_builtin
225 #define __has_builtin(x) 0
228 #ifndef __has_include
229 #define __has_include(x) 0
232 #ifndef __has_feature
233 #define __has_feature(x) 0
236 #if __has_attribute(always_inline) || defined(__GNUC__)
237 #define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline
238 #elif defined(_MSC_VER)
239 #define MPARK_ALWAYS_INLINE __forceinline
241 #define MPARK_ALWAYS_INLINE inline
244 #if __has_builtin(__builtin_addressof) || \
245 (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
246 #define MPARK_BUILTIN_ADDRESSOF
249 #if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
250 #define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable()
251 #elif defined(_MSC_VER)
252 #define MPARK_BUILTIN_UNREACHABLE __assume(false)
254 #define MPARK_BUILTIN_UNREACHABLE
257 #if __has_builtin(__type_pack_element)
258 #define MPARK_TYPE_PACK_ELEMENT
261 #if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
262 !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)
263 #define MPARK_CPP11_CONSTEXPR
266 #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
267 #define MPARK_CPP14_CONSTEXPR
270 #if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
271 (defined(_MSC_VER) && defined(_CPPUNWIND))
272 #define MPARK_EXCEPTIONS
275 #if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
276 #define MPARK_GENERIC_LAMBDAS
279 #if defined(__cpp_lib_integer_sequence)
280 #define MPARK_INTEGER_SEQUENCE
283 #if defined(__cpp_return_type_deduction) || defined(_MSC_VER)
284 #define MPARK_RETURN_TYPE_DEDUCTION
287 #if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
288 #define MPARK_TRANSPARENT_OPERATORS
291 #if defined(__cpp_variable_templates) || defined(_MSC_VER)
292 #define MPARK_VARIABLE_TEMPLATES
295 #if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5
296 #define MPARK_TRIVIALITY_TYPE_TRAITS
297 #define MPARK_INCOMPLETE_TYPE_TRAITS
300 #endif // MPARK_CONFIG_HPP
309 #ifndef MPARK_IN_PLACE_HPP
310 #define MPARK_IN_PLACE_HPP
319 template <std::
size_t I>
322 template <
typename T>
325 #ifdef MPARK_VARIABLE_TEMPLATES
328 template <std::
size_t I> constexpr in_place_index_t<I> in_place_index{};
330 template <
typename T> constexpr in_place_type_t<T> in_place_type{};
335 #endif // MPARK_IN_PLACE_HPP
344 #ifndef MPARK_LIB_HPP
345 #define MPARK_LIB_HPP
348 #include <functional>
349 #include <type_traits>
353 #define MPARK_RETURN(...) \
354 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
358 template <
typename T>
361 inline namespace cpp14 {
362 template <
typename T, std::
size_t N>
364 constexpr
const T &operator[](std::size_t index)
const {
368 T data[N == 0 ? 1 : N];
371 template <
typename T>
372 using add_pointer_t =
typename std::add_pointer<T>::type;
374 template <
typename... Ts>
375 using common_type_t =
typename std::common_type<Ts...>::type;
377 template <
typename T>
378 using decay_t =
typename std::decay<T>::type;
380 template <
bool B,
typename T =
void>
381 using enable_if_t =
typename std::enable_if<B, T>::type;
383 template <
typename T>
384 using remove_const_t =
typename std::remove_const<T>::type;
386 template <
typename T>
387 using remove_reference_t =
typename std::remove_reference<T>::type;
389 template <
typename T>
390 inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
391 return static_cast<T &&
>(t);
394 template <
typename T>
395 inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
396 static_assert(!std::is_lvalue_reference<T>::value,
397 "can not forward an rvalue as an lvalue");
398 return static_cast<T &&
>(t);
401 template <
typename T>
402 inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
403 return static_cast<remove_reference_t<T> &&
>(t);
406 #ifdef MPARK_INTEGER_SEQUENCE
407 using std::integer_sequence;
408 using std::index_sequence;
409 using std::make_index_sequence;
410 using std::index_sequence_for;
412 template <
typename T, T... Is>
414 using value_type = T;
415 static constexpr std::size_t size() noexcept {
return sizeof...(Is); }
418 template <std::size_t... Is>
421 template <
typename Lhs,
typename Rhs>
424 template <std::size_t... Lhs, std::size_t... Rhs>
426 index_sequence<Rhs...>>
427 :
identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
429 template <std::
size_t N>
432 template <std::
size_t N>
435 template <std::
size_t N>
438 make_index_sequence<N - (N / 2)>> {};
446 template <
typename... Ts>
447 using index_sequence_for = make_index_sequence<
sizeof...(Ts)>;
451 #ifdef MPARK_TRANSPARENT_OPERATORS
455 template <
typename Lhs,
typename Rhs>
456 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
457 MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
461 #ifdef MPARK_TRANSPARENT_OPERATORS
465 template <
typename Lhs,
typename Rhs>
466 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
467 MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
471 #ifdef MPARK_TRANSPARENT_OPERATORS
472 using less = std::less<>;
475 template <
typename Lhs,
typename Rhs>
476 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
477 MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
481 #ifdef MPARK_TRANSPARENT_OPERATORS
482 using greater = std::greater<>;
485 template <
typename Lhs,
typename Rhs>
486 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
487 MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
491 #ifdef MPARK_TRANSPARENT_OPERATORS
495 template <
typename Lhs,
typename Rhs>
496 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
497 MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
501 #ifdef MPARK_TRANSPARENT_OPERATORS
505 template <
typename Lhs,
typename Rhs>
506 inline constexpr
auto operator()(Lhs &&lhs, Rhs &&rhs)
const
507 MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
512 inline namespace cpp17 {
516 using bool_constant = std::integral_constant<bool, B>;
518 template <
typename...>
521 template <
typename... Ts>
522 using void_t =
typename voider<Ts...>::type;
525 namespace swappable {
529 template <
typename T>
532 template <
typename U,
533 typename = decltype(swap(std::declval<U &>(),
534 std::declval<U &>()))>
535 inline static std::true_type test(
int);
537 template <
typename U>
538 inline static std::false_type test(...);
541 static constexpr
bool value = decltype(test<T>(0))::value;
544 template <
bool IsSwappable,
typename T>
546 static constexpr
bool value =
547 noexcept(swap(std::declval<T &>(), std::declval<T &>()));
550 template <
typename T>
558 template <
typename T>
565 template <
typename T>
568 template <
typename T>
577 template <
typename R,
typename T,
typename Arg,
typename... Args>
578 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
579 MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
584 template <
typename R,
typename T,
typename Arg,
typename... Args>
585 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
586 MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
591 template <
typename R,
typename T,
typename Arg,
typename... Args>
592 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
593 MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
598 template <
typename R,
typename T,
typename Arg>
599 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
600 MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
605 template <
typename R,
typename T,
typename Arg>
606 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
607 MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
612 template <
typename R,
typename T,
typename Arg>
613 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
614 MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
617 template <
typename R,
typename T,
typename Arg,
typename... Args>
618 inline constexpr
auto invoke(R T::*f, Arg &&arg, Args &&... args)
620 Invoke<std::is_function<R>::value,
621 (std::is_base_of<T, lib::decay_t<Arg>>::value
626 lib::forward<Arg>(arg),
627 lib::forward<Args>(args)...))
630 #pragma warning(push)
631 #pragma warning(disable : 4100)
633 template <
typename F,
typename... Args>
634 inline constexpr
auto invoke(F &&f, Args &&... args)
635 MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
641 template <
typename F,
typename... Args>
642 inline constexpr
auto invoke(F &&f, Args &&... args)
643 MPARK_RETURN(detail::invoke(lib::forward<F>(f),
644 lib::forward<Args>(args)...))
648 template <
typename Void,
typename,
typename...>
649 struct invoke_result {};
651 template <
typename F,
typename... Args>
652 struct invoke_result<void_t<decltype(lib::invoke(
653 std::declval<F>(), std::declval<Args>()...))>,
657 lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
661 template <
typename F,
typename... Args>
662 using invoke_result = detail::invoke_result<void, F, Args...>;
664 template <
typename F,
typename... Args>
665 using invoke_result_t =
typename invoke_result<F, Args...>::type;
669 template <
typename Void,
typename,
typename...>
672 template <
typename F,
typename... Args>
676 template <
typename Void,
typename,
typename,
typename...>
679 template <
typename R,
typename F,
typename... Args>
684 : std::is_convertible<invoke_result_t<F, Args...>, R> {};
688 template <
typename F,
typename... Args>
691 template <
typename R,
typename F,
typename... Args>
696 template <
bool Invocable,
typename F,
typename... Args>
698 static constexpr
bool value =
699 noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...));
702 template <
typename F,
typename... Args>
705 template <
bool Invocable,
typename R,
typename F,
typename... Args>
708 inline static R impl() {
709 return lib::invoke(std::declval<F>(), std::declval<Args>()...);
713 static constexpr
bool value = noexcept(impl());
716 template <
typename R,
typename F,
typename... Args>
721 template <
typename F,
typename... Args>
723 is_nothrow_invocable<
is_invocable<F, Args...>::value, F, Args...>;
725 template <
typename R,
typename F,
typename... Args>
733 #ifdef MPARK_BUILTIN_ADDRESSOF
734 template <
typename T>
735 inline constexpr T *addressof(T &arg) noexcept {
736 return __builtin_addressof(arg);
741 namespace has_addressof_impl {
745 template <
typename T>
746 inline fail operator&(T &&);
748 template <
typename T>
749 inline static constexpr
bool impl() {
750 return (std::is_class<T>::value || std::is_union<T>::value) &&
751 !std::is_same<decltype(&std::declval<T &>()), fail>::value;
756 template <
typename T>
757 using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
759 template <
typename T>
760 inline constexpr T *addressof(T &arg, std::true_type) noexcept {
761 return std::addressof(arg);
764 template <
typename T>
765 inline constexpr T *addressof(T &arg, std::false_type) noexcept {
771 template <
typename T>
772 inline constexpr T *addressof(T &arg) noexcept {
773 return detail::addressof(arg, detail::has_addressof<T>{});
777 template <
typename T>
778 inline constexpr T *addressof(
const T &&) =
delete;
782 template <
typename T>
785 template <
typename T, std::
size_t N>
788 template <
typename T>
789 using remove_all_extents_t =
typename remove_all_extents<T>::type;
791 template <std::
size_t N>
792 using size_constant = std::integral_constant<std::size_t, N>;
794 template <std::
size_t I,
typename T>
797 template <
bool... Bs>
801 #ifdef MPARK_TYPE_PACK_ELEMENT
802 template <std::size_t I,
typename... Ts>
803 using type_pack_element_t = __type_pack_element<I, Ts...>;
805 template <std::size_t I,
typename... Ts>
811 template <std::size_t... Is>
812 struct set<index_sequence<Is...>> :
indexed_type<Is, Ts>... {};
814 template <
typename T>
817 inline static std::enable_if<false> impl(...);
820 using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
823 template <std::size_t I,
typename... Ts>
826 template <std::size_t I,
typename... Ts>
827 using type_pack_element_t =
typename type_pack_element<I, Ts...>::type;
830 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
831 using std::is_trivially_copy_constructible;
832 using std::is_trivially_move_constructible;
833 using std::is_trivially_copy_assignable;
834 using std::is_trivially_move_assignable;
836 template <
typename T>
837 struct is_trivially_copy_constructible
839 std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
841 template <
typename T>
842 struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
844 template <
typename T>
845 struct is_trivially_copy_assignable
847 std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
849 template <
typename T>
850 struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
853 template <
typename T,
bool>
856 template <
typename Is, std::
size_t J>
859 template <
typename Is, std::
size_t J>
862 template <std::size_t... Is, std::size_t J>
864 using type = index_sequence<Is..., J>;
872 #endif // MPARK_LIB_HPP
877 #ifdef MPARK_RETURN_TYPE_DEDUCTION
880 #define AUTO_RETURN(...) { return __VA_ARGS__; }
882 #define AUTO_REFREF auto &&
883 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
885 #define DECLTYPE_AUTO decltype(auto)
886 #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }
891 #define AUTO_RETURN(...) \
892 -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
894 #define AUTO_REFREF auto
895 #define AUTO_REFREF_RETURN(...) \
896 -> decltype((__VA_ARGS__)) { \
897 static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
898 return __VA_ARGS__; \
901 #define DECLTYPE_AUTO auto
902 #define DECLTYPE_AUTO_RETURN(...) \
903 -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
909 virtual const char *what()
const noexcept
override {
return "bad_variant_access"; }
912 [[noreturn]]
inline void throw_bad_variant_access() {
913 #ifdef MPARK_EXCEPTIONS
917 MPARK_BUILTIN_UNREACHABLE;
921 template <
typename... Ts>
924 template <
typename T>
927 #ifdef MPARK_VARIABLE_TEMPLATES
928 template <
typename T>
932 template <
typename T>
935 template <
typename T>
938 template <
typename T>
941 template <
typename... Ts>
944 template <std::
size_t I,
typename T>
947 template <std::
size_t I,
typename T>
950 template <std::
size_t I,
typename T>
952 : std::add_const<variant_alternative_t<I, T>> {};
954 template <std::
size_t I,
typename T>
956 : std::add_volatile<variant_alternative_t<I, T>> {};
958 template <std::
size_t I,
typename T>
960 : std::add_cv<variant_alternative_t<I, T>> {};
962 template <std::size_t I,
typename... Ts>
964 static_assert(I <
sizeof...(Ts),
965 "index out of bounds in `std::variant_alternative<>`");
966 using type = lib::type_pack_element_t<I, Ts...>;
969 constexpr std::size_t variant_npos =
static_cast<std::size_t
>(-1);
973 constexpr std::size_t not_found =
static_cast<std::size_t
>(-1);
974 constexpr std::size_t ambiguous =
static_cast<std::size_t
>(-2);
976 #ifdef MPARK_CPP14_CONSTEXPR
977 template <
typename T,
typename... Ts>
978 inline constexpr std::size_t find_index() {
979 constexpr
lib::array<bool,
sizeof...(Ts)> matches = {
980 {std::is_same<T, Ts>::value...}
982 std::size_t result = not_found;
983 for (std::size_t i = 0; i <
sizeof...(Ts); ++i) {
985 if (result != not_found) {
994 inline constexpr std::size_t find_index_impl(std::size_t result,
999 template <
typename... Bs>
1000 inline constexpr std::size_t find_index_impl(std::size_t result,
1004 return b ? (result != not_found ? ambiguous
1005 : find_index_impl(idx, idx + 1, bs...))
1006 : find_index_impl(result, idx + 1, bs...);
1009 template <
typename T,
typename... Ts>
1010 inline constexpr std::size_t find_index() {
1011 return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);
1015 template <std::
size_t I>
1016 using find_index_sfinae_impl =
1017 lib::enable_if_t<I != not_found && I != ambiguous,
1018 lib::size_constant<I>>;
1020 template <
typename T,
typename... Ts>
1021 using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
1023 template <std::
size_t I>
1025 static_assert(I != not_found,
"the specified type is not found.");
1026 static_assert(I != ambiguous,
"the specified type is ambiguous.");
1029 template <
typename T,
typename... Ts>
1034 enum class Trait { TriviallyAvailable, Available, Unavailable };
1036 template <
typename T,
1037 template <
typename>
class IsTriviallyAvailable,
1038 template <
typename>
class IsAvailable>
1039 inline constexpr Trait trait() {
1040 return IsTriviallyAvailable<T>::value
1041 ? Trait::TriviallyAvailable
1042 : IsAvailable<T>::value ? Trait::Available
1043 : Trait::Unavailable;
1046 #ifdef MPARK_CPP14_CONSTEXPR
1047 template <
typename... Traits>
1048 inline constexpr Trait common_trait(Traits... traits_) {
1049 Trait result = Trait::TriviallyAvailable;
1050 lib::array<Trait,
sizeof...(Traits)> traits = {{traits_...}};
1051 for (std::size_t i = 0; i <
sizeof...(Traits); ++i) {
1052 Trait t = traits[i];
1053 if (
static_cast<int>(t) >
static_cast<int>(result)) {
1060 inline constexpr Trait common_trait_impl(Trait result) {
return result; }
1062 template <
typename... Traits>
1063 inline constexpr Trait common_trait_impl(Trait result,
1066 return static_cast<int>(t) >
static_cast<int>(result)
1067 ? common_trait_impl(t, ts...)
1068 : common_trait_impl(result, ts...);
1071 template <
typename... Traits>
1072 inline constexpr Trait common_trait(Traits... ts) {
1073 return common_trait_impl(Trait::TriviallyAvailable, ts...);
1077 template <
typename... Ts>
1079 static constexpr Trait copy_constructible_trait =
1080 common_trait(trait<Ts,
1081 lib::is_trivially_copy_constructible,
1082 std::is_copy_constructible>()...);
1084 static constexpr Trait move_constructible_trait =
1085 common_trait(trait<Ts,
1086 lib::is_trivially_move_constructible,
1087 std::is_move_constructible>()...);
1089 static constexpr Trait copy_assignable_trait =
1090 common_trait(copy_constructible_trait,
1092 lib::is_trivially_copy_assignable,
1093 std::is_copy_assignable>()...);
1095 static constexpr Trait move_assignable_trait =
1096 common_trait(move_constructible_trait,
1098 lib::is_trivially_move_assignable,
1099 std::is_move_assignable>()...);
1101 static constexpr Trait destructible_trait =
1102 common_trait(trait<Ts,
1103 std::is_trivially_destructible,
1104 std::is_destructible>()...);
1110 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1111 template <
typename V>
1113 return lib::forward<V>(v).head_;
1116 template <
typename V, std::
size_t I>
1121 template <std::
size_t I,
bool Dummy = true>
1123 template <
typename V>
1124 inline constexpr AUTO_REFREF operator()(V &&v)
const
1128 template <
bool Dummy>
1130 template <
typename V>
1131 inline constexpr AUTO_REFREF operator()(V &&v)
const
1132 AUTO_REFREF_RETURN(lib::forward<V>(v).head_)
1135 template <
typename V, std::
size_t I>
1142 template <std::
size_t I,
typename V>
1143 inline static constexpr AUTO_REFREF get_alt(V &&v)
1145 AUTO_REFREF_RETURN(recursive_union::get_alt(
1148 AUTO_REFREF_RETURN(recursive_union::get_alt(
1154 template <std::
size_t I,
typename V>
1155 inline static constexpr AUTO_REFREF get_alt(V &&v)
1156 AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))
1161 namespace visitation {
1163 #if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER)
1164 #define MPARK_VARIANT_SWITCH_VISIT
1168 template <
typename Visitor,
typename... Vs>
1169 using dispatch_result_t = decltype(
1170 lib::invoke(std::declval<Visitor>(),
1171 access::base::get_alt<0>(std::declval<Vs>())...));
1173 template <
typename Expected>
1175 template <
typename Actual>
1176 inline static constexpr
bool but_got() {
1177 return std::is_same<Expected, Actual>::value;
1181 template <
typename Expected,
typename Actual>
1185 "`visit` requires the visitor to have a single return type");
1187 template <
typename Visitor,
typename... Alts>
1188 inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
1190 DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
1191 lib::forward<Alts>(alts)...))
1194 #ifdef MPARK_VARIANT_SWITCH_VISIT
1195 template <
bool B,
typename R,
typename... ITs>
1198 template <
typename R,
typename... ITs>
1199 struct dispatcher<false, R, ITs...> {
1200 template <std::size_t B,
typename F,
typename... Vs>
1201 MPARK_ALWAYS_INLINE
static constexpr R dispatch(
1202 F &&,
typename ITs::type &&..., Vs &&...) {
1203 MPARK_BUILTIN_UNREACHABLE;
1206 template <std::size_t I,
typename F,
typename... Vs>
1207 MPARK_ALWAYS_INLINE
static constexpr R dispatch_case(F &&, Vs &&...) {
1208 MPARK_BUILTIN_UNREACHABLE;
1211 template <std::size_t B,
typename F,
typename... Vs>
1212 MPARK_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t,
1215 MPARK_BUILTIN_UNREACHABLE;
1219 template <
typename R,
typename... ITs>
1220 struct dispatcher<true, R, ITs...> {
1221 template <std::
size_t B,
typename F>
1222 MPARK_ALWAYS_INLINE
static constexpr R dispatch(
1223 F &&f,
typename ITs::type &&... visited_vs) {
1225 using Actual = decltype(lib::invoke(
1227 access::base::get_alt<ITs::value>(
1228 lib::forward<typename ITs::type>(visited_vs))...));
1229 return visit_return_type_check<Expected, Actual>::invoke(
1231 access::base::get_alt<ITs::value>(
1232 lib::forward<typename ITs::type>(visited_vs))...);
1235 template <std::size_t B,
typename F,
typename V,
typename... Vs>
1236 MPARK_ALWAYS_INLINE
static constexpr R dispatch(
1237 F &&f,
typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
1238 #define MPARK_DISPATCH(I) \
1239 dispatcher<(I < lib::decay_t<V>::size()), \
1242 lib::indexed_type<I, V>>:: \
1243 template dispatch<0>(lib::forward<F>(f), \
1244 lib::forward<typename ITs::type>(visited_vs)..., \
1245 lib::forward<V>(v), \
1246 lib::forward<Vs>(vs)...)
1248 #define MPARK_DEFAULT(I) \
1249 dispatcher<(I < lib::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
1250 lib::forward<F>(f), \
1251 lib::forward<typename ITs::type>(visited_vs)..., \
1252 lib::forward<V>(v), \
1253 lib::forward<Vs>(vs)...)
1255 switch (v.index()) {
1256 case B + 0:
return MPARK_DISPATCH(B + 0);
1257 case B + 1:
return MPARK_DISPATCH(B + 1);
1258 case B + 2:
return MPARK_DISPATCH(B + 2);
1259 case B + 3:
return MPARK_DISPATCH(B + 3);
1260 case B + 4:
return MPARK_DISPATCH(B + 4);
1261 case B + 5:
return MPARK_DISPATCH(B + 5);
1262 case B + 6:
return MPARK_DISPATCH(B + 6);
1263 case B + 7:
return MPARK_DISPATCH(B + 7);
1264 case B + 8:
return MPARK_DISPATCH(B + 8);
1265 case B + 9:
return MPARK_DISPATCH(B + 9);
1266 case B + 10:
return MPARK_DISPATCH(B + 10);
1267 case B + 11:
return MPARK_DISPATCH(B + 11);
1268 case B + 12:
return MPARK_DISPATCH(B + 12);
1269 case B + 13:
return MPARK_DISPATCH(B + 13);
1270 case B + 14:
return MPARK_DISPATCH(B + 14);
1271 case B + 15:
return MPARK_DISPATCH(B + 15);
1272 case B + 16:
return MPARK_DISPATCH(B + 16);
1273 case B + 17:
return MPARK_DISPATCH(B + 17);
1274 case B + 18:
return MPARK_DISPATCH(B + 18);
1275 case B + 19:
return MPARK_DISPATCH(B + 19);
1276 case B + 20:
return MPARK_DISPATCH(B + 20);
1277 case B + 21:
return MPARK_DISPATCH(B + 21);
1278 case B + 22:
return MPARK_DISPATCH(B + 22);
1279 case B + 23:
return MPARK_DISPATCH(B + 23);
1280 case B + 24:
return MPARK_DISPATCH(B + 24);
1281 case B + 25:
return MPARK_DISPATCH(B + 25);
1282 case B + 26:
return MPARK_DISPATCH(B + 26);
1283 case B + 27:
return MPARK_DISPATCH(B + 27);
1284 case B + 28:
return MPARK_DISPATCH(B + 28);
1285 case B + 29:
return MPARK_DISPATCH(B + 29);
1286 case B + 30:
return MPARK_DISPATCH(B + 30);
1287 case B + 31:
return MPARK_DISPATCH(B + 31);
1288 default:
return MPARK_DEFAULT(B + 32);
1291 #undef MPARK_DEFAULT
1292 #undef MPARK_DISPATCH
1295 template <std::size_t I,
typename F,
typename... Vs>
1296 MPARK_ALWAYS_INLINE
static constexpr R dispatch_case(F &&f,
1299 using Actual = decltype(
1300 lib::invoke(lib::forward<F>(f),
1301 access::base::get_alt<I>(lib::forward<Vs>(vs))...));
1302 return visit_return_type_check<Expected, Actual>::invoke(
1304 access::base::get_alt<I>(lib::forward<Vs>(vs))...);
1307 template <std::size_t B,
typename F,
typename V,
typename... Vs>
1308 MPARK_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t index,
1312 static_assert(lib::all<(lib::decay_t<V>::size() ==
1313 lib::decay_t<Vs>::size())...>::value,
1314 "all of the variants must be the same size.");
1315 #define MPARK_DISPATCH_AT(I) \
1316 dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_case<I>( \
1317 lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
1319 #define MPARK_DEFAULT(I) \
1320 dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_at<I>( \
1321 index, lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
1324 case B + 0:
return MPARK_DISPATCH_AT(B + 0);
1325 case B + 1:
return MPARK_DISPATCH_AT(B + 1);
1326 case B + 2:
return MPARK_DISPATCH_AT(B + 2);
1327 case B + 3:
return MPARK_DISPATCH_AT(B + 3);
1328 case B + 4:
return MPARK_DISPATCH_AT(B + 4);
1329 case B + 5:
return MPARK_DISPATCH_AT(B + 5);
1330 case B + 6:
return MPARK_DISPATCH_AT(B + 6);
1331 case B + 7:
return MPARK_DISPATCH_AT(B + 7);
1332 case B + 8:
return MPARK_DISPATCH_AT(B + 8);
1333 case B + 9:
return MPARK_DISPATCH_AT(B + 9);
1334 case B + 10:
return MPARK_DISPATCH_AT(B + 10);
1335 case B + 11:
return MPARK_DISPATCH_AT(B + 11);
1336 case B + 12:
return MPARK_DISPATCH_AT(B + 12);
1337 case B + 13:
return MPARK_DISPATCH_AT(B + 13);
1338 case B + 14:
return MPARK_DISPATCH_AT(B + 14);
1339 case B + 15:
return MPARK_DISPATCH_AT(B + 15);
1340 case B + 16:
return MPARK_DISPATCH_AT(B + 16);
1341 case B + 17:
return MPARK_DISPATCH_AT(B + 17);
1342 case B + 18:
return MPARK_DISPATCH_AT(B + 18);
1343 case B + 19:
return MPARK_DISPATCH_AT(B + 19);
1344 case B + 20:
return MPARK_DISPATCH_AT(B + 20);
1345 case B + 21:
return MPARK_DISPATCH_AT(B + 21);
1346 case B + 22:
return MPARK_DISPATCH_AT(B + 22);
1347 case B + 23:
return MPARK_DISPATCH_AT(B + 23);
1348 case B + 24:
return MPARK_DISPATCH_AT(B + 24);
1349 case B + 25:
return MPARK_DISPATCH_AT(B + 25);
1350 case B + 26:
return MPARK_DISPATCH_AT(B + 26);
1351 case B + 27:
return MPARK_DISPATCH_AT(B + 27);
1352 case B + 28:
return MPARK_DISPATCH_AT(B + 28);
1353 case B + 29:
return MPARK_DISPATCH_AT(B + 29);
1354 case B + 30:
return MPARK_DISPATCH_AT(B + 30);
1355 case B + 31:
return MPARK_DISPATCH_AT(B + 31);
1356 default:
return MPARK_DEFAULT(B + 32);
1359 #undef MPARK_DEFAULT
1360 #undef MPARK_DISPATCH_AT
1364 template <
typename T>
1365 inline static constexpr
const T &at(
const T &elem) noexcept {
1369 template <
typename T, std::size_t N,
typename... Is>
1370 inline static constexpr
const lib::remove_all_extents_t<T> &at(
1371 const lib::array<T, N> &elems, std::size_t i, Is... is) noexcept {
1372 return at(elems[i], is...);
1375 template <
typename F,
typename... Fs>
1376 inline static constexpr lib::array<lib::decay_t<F>,
sizeof...(Fs) + 1>
1377 make_farray(F &&f, Fs &&... fs) {
1378 return {{lib::forward<F>(f), lib::forward<Fs>(fs)...}};
1381 template <
typename F,
typename... Vs>
1384 template <std::size_t... Is>
1385 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
1386 F &&f, Vs &&... vs) {
1387 using Expected = dispatch_result_t<F, Vs...>;
1388 using Actual = decltype(lib::invoke(
1390 access::base::get_alt<Is>(lib::forward<Vs>(vs))...));
1393 access::base::get_alt<Is>(lib::forward<Vs>(vs))...);
1396 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1397 template <std::size_t... Is>
1398 inline static constexpr
auto impl(lib::index_sequence<Is...>) {
1399 return &dispatch<Is...>;
1402 template <
typename Is, std::size_t... Js,
typename... Ls>
1403 inline static constexpr
auto impl(Is,
1404 lib::index_sequence<Js...>,
1406 return make_farray(
impl(lib::push_back_t<Is, Js>{}, ls...)...);
1409 template <
typename...>
1412 template <std::size_t... Is>
1413 struct impl<lib::index_sequence<Is...>> {
1414 inline constexpr AUTO operator()()
const
1415 AUTO_RETURN(&dispatch<Is...>)
1418 template <
typename Is, std::size_t... Js,
typename... Ls>
1419 struct impl<Is, lib::index_sequence<Js...>, Ls...> {
1420 inline constexpr AUTO operator()()
const
1422 make_farray(
impl<lib::push_back_t<Is, Js>, Ls...>{}()...))
1427 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1428 template <
typename F,
typename... Vs>
1429 inline static constexpr
auto make_fmatrix() {
1431 lib::index_sequence<>{},
1432 lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);
1435 template <
typename F,
typename... Vs>
1436 inline static constexpr AUTO make_fmatrix()
1438 typename make_fmatrix_impl<F, Vs...>::template impl<
1439 lib::index_sequence<>,
1440 lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
1443 template <
typename F,
typename... Vs>
1445 template <std::
size_t I>
1446 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
1447 F &&f, Vs &&... vs) {
1448 using Expected = dispatch_result_t<F, Vs...>;
1449 using Actual = decltype(
1450 lib::invoke(lib::forward<F>(f),
1451 access::base::get_alt<I>(lib::forward<Vs>(vs))...));
1454 access::base::get_alt<I>(lib::forward<Vs>(vs))...);
1457 template <std::size_t... Is>
1458 inline static constexpr AUTO
impl(lib::index_sequence<Is...>)
1459 AUTO_RETURN(make_farray(&dispatch<Is>...))
1462 template <
typename F,
typename V,
typename... Vs>
1463 inline static constexpr
auto make_fdiagonal()
1465 lib::make_index_sequence<lib::decay_t<V>::size()>{})) {
1466 static_assert(lib::all<(lib::decay_t<V>::size() ==
1467 lib::decay_t<Vs>::size())...>::value,
1468 "all of the variants must be the same size.");
1469 return make_fdiagonal_impl<F, V, Vs...>::impl(
1470 lib::make_index_sequence<lib::decay_t<V>::size()>{});
1475 #if !defined(MPARK_VARIANT_SWITCH_VISIT) && \
1476 (!defined(_MSC_VER) || _MSC_VER >= 1910)
1477 template <
typename F,
typename... Vs>
1478 using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
1480 template <
typename F,
typename... Vs>
1482 static constexpr fmatrix_t<F, Vs...> value =
1483 base::make_fmatrix<F, Vs...>();
1486 template <
typename F,
typename... Vs>
1487 constexpr fmatrix_t<F, Vs...>
fmatrix<F, Vs...>::value;
1489 template <
typename F,
typename... Vs>
1490 using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
1492 template <
typename F,
typename... Vs>
1494 static constexpr fdiagonal_t<F, Vs...> value =
1495 base::make_fdiagonal<F, Vs...>();
1498 template <
typename F,
typename... Vs>
1499 constexpr fdiagonal_t<F, Vs...>
fdiagonal<F, Vs...>::value;
1503 template <
typename Visitor,
typename... Vs>
1504 inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
1506 #ifdef MPARK_VARIANT_SWITCH_VISIT
1507 DECLTYPE_AUTO_RETURN(
1510 base::dispatch_result_t<Visitor,
1512 lib::forward<Vs>(vs)))...>>::
1513 template dispatch<0>(lib::forward<Visitor>(visitor),
1514 as_base(lib::forward<Vs>(vs))...))
1515 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
1516 DECLTYPE_AUTO_RETURN(base::at(
1518 decltype(as_base(lib::forward<Vs>(vs)))...>::value,
1519 vs.index()...)(lib::forward<Visitor>(visitor),
1520 as_base(lib::forward<Vs>(vs))...))
1522 DECLTYPE_AUTO_RETURN(base::at(
1523 base::make_fmatrix<Visitor &&,
1524 decltype(as_base(lib::forward<Vs>(vs)))...>(),
1525 vs.index()...)(lib::forward<Visitor>(visitor),
1526 as_base(lib::forward<Vs>(vs))...))
1529 template <typename Visitor, typename... Vs>
1530 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
1533 #ifdef MPARK_VARIANT_SWITCH_VISIT
1534 DECLTYPE_AUTO_RETURN(
1537 base::dispatch_result_t<Visitor,
1539 lib::forward<Vs>(vs)))...>>::
1540 template dispatch_at<0>(index,
1541 lib::forward<Visitor>(visitor),
1542 as_base(lib::forward<Vs>(vs))...))
1543 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
1544 DECLTYPE_AUTO_RETURN(base::at(
1546 decltype(as_base(lib::forward<Vs>(vs)))...>::value,
1547 index)(lib::forward<Visitor>(visitor),
1548 as_base(lib::forward<Vs>(vs))...))
1550 DECLTYPE_AUTO_RETURN(base::at(
1551 base::make_fdiagonal<Visitor &&,
1552 decltype(as_base(lib::forward<Vs>(vs)))...>(),
1553 index)(lib::forward<Visitor>(visitor),
1554 as_base(lib::forward<Vs>(vs))...))
1560 template <
typename Visitor>
1562 template <
typename... Values>
1563 inline static constexpr
bool does_not_handle() {
1564 return lib::is_invocable<Visitor, Values...>::value;
1568 template <
typename Visitor,
typename... Values>
1569 struct visit_exhaustiveness_check {
1570 static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
1571 "`visit` requires the visitor to be exhaustive.");
1573 inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
1574 Values &&... values)
1575 DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
1576 lib::forward<Values>(values)...))
1579 template <
typename Visitor>
1580 struct value_visitor {
1583 template <
typename... Alts>
1584 inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts)
const
1585 DECLTYPE_AUTO_RETURN(
1586 visit_exhaustiveness_check<
1588 decltype((lib::forward<Alts>(alts).value))...>::
1589 invoke(lib::forward<Visitor>(visitor_),
1590 lib::forward<Alts>(alts).value...))
1593 template <
typename Visitor>
1594 inline static constexpr AUTO make_value_visitor(Visitor &&visitor)
1595 AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})
1598 template <typename Visitor, typename... Vs>
1599 inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
1601 DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),
1602 lib::forward<Vs>(vs).impl_...))
1604 template <
typename Visitor,
typename... Vs>
1605 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
1608 DECLTYPE_AUTO_RETURN(
1609 alt::visit_alt_at(index,
1610 lib::forward<Visitor>(visitor),
1611 lib::forward<Vs>(vs).impl_...))
1613 template <
typename Visitor,
typename... Vs>
1614 inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor,
1616 DECLTYPE_AUTO_RETURN(
1617 visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),
1618 lib::forward<Vs>(vs)...))
1620 template <
typename Visitor,
typename... Vs>
1621 inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index,
1624 DECLTYPE_AUTO_RETURN(
1626 make_value_visitor(lib::forward<Visitor>(visitor)),
1627 lib::forward<Vs>(vs)...))
1632 template <std::
size_t Index,
typename T>
1634 using value_type = T;
1637 #pragma warning(push)
1638 #pragma warning(disable : 4244)
1640 template <
typename... Args>
1642 : value(lib::forward<Args>(args)...) {}
1644 #pragma warning(pop)
1650 template <Trait DestructibleTrait, std::size_t Index,
typename... Ts>
1653 template <Trait DestructibleTrait, std::
size_t Index>
1656 #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
1657 template <std::size_t Index, typename T, typename... Ts> \
1658 union recursive_union<destructible_trait, Index, T, Ts...> { \
1660 inline explicit constexpr recursive_union(valueless_t) noexcept \
1663 template <typename... Args> \
1664 inline explicit constexpr recursive_union(in_place_index_t<0>, \
1666 : head_(in_place_t{}, lib::forward<Args>(args)...) {} \
1668 template <std::size_t I, typename... Args> \
1669 inline explicit constexpr recursive_union(in_place_index_t<I>, \
1671 : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \
1673 recursive_union(const recursive_union &) = default; \
1674 recursive_union(recursive_union &&) = default; \
1678 recursive_union &operator=(const recursive_union &) = default; \
1679 recursive_union &operator=(recursive_union &&) = default; \
1683 alt<Index, T> head_; \
1684 recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
1686 friend struct access::recursive_union; \
1689 MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
1691 MPARK_VARIANT_RECURSIVE_UNION(Trait::Available,
1693 MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
1694 ~recursive_union() =
delete;);
1696 #undef MPARK_VARIANT_RECURSIVE_UNION
1698 using index_t =
unsigned int;
1700 template <Trait DestructibleTrait,
typename... Ts>
1704 : data_(tag), index_(
static_cast<index_t
>(-1)) {}
1706 template <std::size_t I,
typename... Args>
1711 inline constexpr
bool valueless_by_exception()
const noexcept {
1712 return index_ ==
static_cast<index_t
>(-1);
1715 inline constexpr std::size_t index()
const noexcept {
1716 return valueless_by_exception() ? variant_npos : index_;
1722 friend inline constexpr
base &as_base(
base &b) {
return b; }
1723 friend inline constexpr
const base &as_base(
const base &b) {
return b; }
1724 friend inline constexpr
base &&as_base(
base &&b) {
return lib::move(b); }
1725 friend inline constexpr
const base &&as_base(
const base &&b) {
return lib::move(b); }
1727 friend inline constexpr
data_t &data(
base &b) {
return b.data_; }
1728 friend inline constexpr
const data_t &data(
const base &b) {
return b.data_; }
1729 friend inline constexpr
data_t &&data(
base &&b) {
return lib::move(b).data_; }
1730 friend inline constexpr
const data_t &&data(
const base &&b) {
return lib::move(b).data_; }
1732 inline static constexpr std::size_t size() {
return sizeof...(Ts); }
1743 #pragma warning(push)
1744 #pragma warning(disable : 4100)
1746 template <
typename Alt>
1747 inline void operator()(Alt &
alt)
const noexcept {
alt.~Alt(); }
1749 #pragma warning(pop)
1753 #if !defined(_MSC_VER) || _MSC_VER >= 1910
1754 #define MPARK_INHERITING_CTOR(type, base) using base::base;
1756 #define MPARK_INHERITING_CTOR(type, base) \
1757 template <typename... Args> \
1758 inline explicit constexpr type(Args &&... args) \
1759 : base(lib::forward<Args>(args)...) {}
1762 template <
typename Traits, Trait = Traits::destructible_trait>
1765 #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
1766 template <typename... Ts> \
1767 class destructor<traits<Ts...>, destructible_trait> \
1768 : public base<destructible_trait, Ts...> { \
1769 using super = base<destructible_trait, Ts...>; \
1772 MPARK_INHERITING_CTOR(destructor, super) \
1773 using super::operator=; \
1775 destructor(const destructor &) = default; \
1776 destructor(destructor &&) = default; \
1778 destructor &operator=(const destructor &) = default; \
1779 destructor &operator=(destructor &&) = default; \
1785 MPARK_VARIANT_DESTRUCTOR(
1786 Trait::TriviallyAvailable,
1788 inline void destroy() noexcept {
1789 this->index_ =
static_cast<index_t
>(-1);
1792 MPARK_VARIANT_DESTRUCTOR(
1795 inline void destroy() noexcept {
1796 if (!this->valueless_by_exception()) {
1797 visitation::alt::visit_alt(dtor{}, *
this);
1799 this->index_ =
static_cast<index_t
>(-1);
1802 MPARK_VARIANT_DESTRUCTOR(
1804 ~destructor() =
delete;,
1805 inline void destroy() noexcept = delete;);
1807 #undef MPARK_VARIANT_DESTRUCTOR
1809 template <
typename Traits>
1815 using super::operator=;
1818 #ifndef MPARK_GENERIC_LAMBDAS
1820 template <
typename LhsAlt,
typename RhsAlt>
1821 inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt)
const {
1822 constructor::construct_alt(lhs_alt,
1823 lib::forward<RhsAlt>(rhs_alt).value);
1828 template <std::size_t I,
typename T,
typename... Args>
1829 inline static T &construct_alt(
alt<I, T> &a, Args &&... args) {
1830 auto *result = ::new (
static_cast<void *
>(lib::addressof(a)))
1832 return result->value;
1835 template <
typename Rhs>
1836 inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
1838 if (!rhs.valueless_by_exception()) {
1839 visitation::alt::visit_alt_at(
1841 #ifdef MPARK_GENERIC_LAMBDAS
1842 [](
auto &lhs_alt,
auto &&rhs_alt) {
1843 constructor::construct_alt(
1844 lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);
1851 lib::forward<Rhs>(rhs));
1852 lhs.index_ = rhs.index_;
1857 template <
typename Traits, Trait = Traits::move_constructible_trait>
1860 #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
1861 template <typename... Ts> \
1862 class move_constructor<traits<Ts...>, move_constructible_trait> \
1863 : public constructor<traits<Ts...>> { \
1864 using super = constructor<traits<Ts...>>; \
1867 MPARK_INHERITING_CTOR(move_constructor, super) \
1868 using super::operator=; \
1870 move_constructor(const move_constructor &) = default; \
1872 ~move_constructor() = default; \
1873 move_constructor &operator=(const move_constructor &) = default; \
1874 move_constructor &operator=(move_constructor &&) = default; \
1877 MPARK_VARIANT_MOVE_CONSTRUCTOR(
1878 Trait::TriviallyAvailable,
1881 MPARK_VARIANT_MOVE_CONSTRUCTOR(
1884 lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
1886 this->generic_construct(*
this, lib::move(that));
1889 MPARK_VARIANT_MOVE_CONSTRUCTOR(
1891 move_constructor(move_constructor &&) =
delete;);
1893 #undef MPARK_VARIANT_MOVE_CONSTRUCTOR
1895 template <
typename Traits, Trait = Traits::copy_constructible_trait>
1898 #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
1899 template <typename... Ts> \
1900 class copy_constructor<traits<Ts...>, copy_constructible_trait> \
1901 : public move_constructor<traits<Ts...>> { \
1902 using super = move_constructor<traits<Ts...>>; \
1905 MPARK_INHERITING_CTOR(copy_constructor, super) \
1906 using super::operator=; \
1909 copy_constructor(copy_constructor &&) = default; \
1910 ~copy_constructor() = default; \
1911 copy_constructor &operator=(const copy_constructor &) = default; \
1912 copy_constructor &operator=(copy_constructor &&) = default; \
1915 MPARK_VARIANT_COPY_CONSTRUCTOR(
1916 Trait::TriviallyAvailable,
1919 MPARK_VARIANT_COPY_CONSTRUCTOR(
1923 this->generic_construct(*
this, that);
1926 MPARK_VARIANT_COPY_CONSTRUCTOR(
1928 copy_constructor(
const copy_constructor &) =
delete;);
1930 #undef MPARK_VARIANT_COPY_CONSTRUCTOR
1932 template <
typename Traits>
1938 using super::operator=;
1940 template <std::size_t I,
typename... Args>
1941 inline auto emplace(Args &&... args)
1942 -> decltype(this->construct_alt(access::base::get_alt<I>(*
this),
1943 lib::forward<Args>(args)...)) {
1945 auto &result = this->construct_alt(access::base::get_alt<I>(*
this),
1946 lib::forward<Args>(args)...);
1952 #ifndef MPARK_GENERIC_LAMBDAS
1953 template <
typename That>
1955 template <
typename ThisAlt,
typename ThatAlt>
1956 inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt)
const {
1957 self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);
1963 template <std::
size_t I,
typename T,
typename Arg>
1964 inline void assign_alt(
alt<I, T> &a, Arg &&arg) {
1965 if (this->index() == I) {
1967 #pragma warning(push)
1968 #pragma warning(disable : 4244)
1970 a.value = lib::forward<Arg>(arg);
1972 #pragma warning(pop)
1976 void operator()(std::true_type)
const {
1977 this_->emplace<I>(lib::forward<Arg>(arg_));
1979 void operator()(std::false_type)
const {
1980 this_->emplace<I>(T(lib::forward<Arg>(arg_)));
1984 } impl{
this, lib::forward<Arg>(arg)};
1985 impl(lib::bool_constant<
1986 std::is_nothrow_constructible<T, Arg>::value ||
1987 !std::is_nothrow_move_constructible<T>::value>{});
1991 template <
typename That>
1992 inline void generic_assign(That &&that) {
1993 if (this->valueless_by_exception() && that.valueless_by_exception()) {
1995 }
else if (that.valueless_by_exception()) {
1998 visitation::alt::visit_alt_at(
2000 #ifdef MPARK_GENERIC_LAMBDAS
2001 [
this](
auto &this_alt,
auto &&that_alt) {
2003 this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
2006 assigner<That>{this}
2010 lib::forward<That>(that));
2015 template <
typename Traits, Trait = Traits::move_assignable_trait>
2018 #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
2019 template <typename... Ts> \
2020 class move_assignment<traits<Ts...>, move_assignable_trait> \
2021 : public assignment<traits<Ts...>> { \
2022 using super = assignment<traits<Ts...>>; \
2025 MPARK_INHERITING_CTOR(move_assignment, super) \
2026 using super::operator=; \
2028 move_assignment(const move_assignment &) = default; \
2029 move_assignment(move_assignment &&) = default; \
2030 ~move_assignment() = default; \
2031 move_assignment &operator=(const move_assignment &) = default; \
2035 MPARK_VARIANT_MOVE_ASSIGNMENT(
2036 Trait::TriviallyAvailable,
2039 MPARK_VARIANT_MOVE_ASSIGNMENT(
2043 lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
2044 std::is_nothrow_move_assignable<Ts>::value)...>::value) {
2045 this->generic_assign(lib::move(that));
2049 MPARK_VARIANT_MOVE_ASSIGNMENT(
2053 #undef MPARK_VARIANT_MOVE_ASSIGNMENT
2055 template <
typename Traits, Trait = Traits::copy_assignable_trait>
2058 #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
2059 template <typename... Ts> \
2060 class copy_assignment<traits<Ts...>, copy_assignable_trait> \
2061 : public move_assignment<traits<Ts...>> { \
2062 using super = move_assignment<traits<Ts...>>; \
2065 MPARK_INHERITING_CTOR(copy_assignment, super) \
2066 using super::operator=; \
2068 copy_assignment(const copy_assignment &) = default; \
2069 copy_assignment(copy_assignment &&) = default; \
2070 ~copy_assignment() = default; \
2072 copy_assignment &operator=(copy_assignment &&) = default; \
2075 MPARK_VARIANT_COPY_ASSIGNMENT(
2076 Trait::TriviallyAvailable,
2079 MPARK_VARIANT_COPY_ASSIGNMENT(
2082 this->generic_assign(that);
2086 MPARK_VARIANT_COPY_ASSIGNMENT(
2090 #undef MPARK_VARIANT_COPY_ASSIGNMENT
2092 template <
typename... Ts>
2098 using super::operator=;
2100 template <std::
size_t I,
typename Arg>
2101 inline void assign(Arg &&arg) {
2102 this->assign_alt(access::base::get_alt<I>(*
this),
2103 lib::forward<Arg>(arg));
2106 inline void swap(
impl &that) {
2107 if (this->valueless_by_exception() && that.valueless_by_exception()) {
2109 }
else if (this->index() == that.index()) {
2110 visitation::alt::visit_alt_at(this->index(),
2111 #ifdef MPARK_GENERIC_LAMBDAS
2112 [](
auto &this_alt,
auto &that_alt) {
2114 swap(this_alt.value,
2125 impl *rhs = lib::addressof(that);
2126 if (lhs->move_nothrow() && !rhs->move_nothrow()) {
2127 std::swap(lhs, rhs);
2129 impl tmp(lib::move(*rhs));
2130 #ifdef MPARK_EXCEPTIONS
2135 this->generic_construct(*rhs, lib::move(*lhs));
2137 if (tmp.move_nothrow()) {
2138 this->generic_construct(*rhs, lib::move(tmp));
2143 this->generic_construct(*rhs, lib::move(*lhs));
2145 this->generic_construct(*lhs, lib::move(tmp));
2150 #ifndef MPARK_GENERIC_LAMBDAS
2152 template <
typename ThisAlt,
typename ThatAlt>
2153 inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt)
const {
2155 swap(this_alt.value, that_alt.value);
2160 inline constexpr
bool move_nothrow()
const {
2161 return this->valueless_by_exception() ||
2163 {std::is_nothrow_move_constructible<Ts>::value...}
2168 #undef MPARK_INHERITING_CTOR
2170 template <std::
size_t I,
typename T>
2172 using F = lib::size_constant<I> (*)(T);
2173 operator F()
const {
return nullptr; }
2176 template <
typename... Ts>
2182 template <std::size_t... Is>
2183 struct impl<lib::index_sequence<Is...>> :
overload_leaf<Is, Ts>... {};
2186 using type = impl<lib::index_sequence_for<Ts...>>;
2189 template <
typename... Ts>
2192 template <
typename T,
typename... Ts>
2193 using best_match = lib::invoke_result_t<overload<Ts...>, T &&>;
2195 template <
typename T>
2198 template <std::
size_t I>
2201 template <
typename T>
2204 template <
typename T>
2209 template <
typename... Ts>
2211 static_assert(0 <
sizeof...(Ts),
2212 "variant must consist of at least one alternative.");
2214 static_assert(lib::all<!std::is_array<Ts>::value...>::value,
2215 "variant can not have an array type as an alternative.");
2217 static_assert(lib::all<!std::is_reference<Ts>::value...>::value,
2218 "variant can not have a reference type as an alternative.");
2220 static_assert(lib::all<!std::is_void<Ts>::value...>::value,
2221 "variant can not have a void type as an alternative.");
2225 typename Front = lib::type_pack_element_t<0, Ts...>,
2226 lib::enable_if_t<std::is_default_constructible<Front>::value,
int> = 0>
2227 inline constexpr
variant() noexcept(
2228 std::is_nothrow_default_constructible<Front>::value)
2236 typename Decayed = lib::decay_t<Arg>,
2237 lib::enable_if_t<!std::is_same<Decayed, variant>::value,
int> = 0,
2238 lib::enable_if_t<!detail::is_in_place_index<Decayed>::value,
int> = 0,
2239 lib::enable_if_t<!detail::is_in_place_type<Decayed>::value,
int> = 0,
2240 std::size_t I = detail::best_match<Arg, Ts...>::value,
2241 typename T = lib::type_pack_element_t<I, Ts...>,
2242 lib::enable_if_t<std::is_constructible<T, Arg>::value,
int> = 0>
2243 inline constexpr
variant(Arg &&arg) noexcept(
2244 std::is_nothrow_constructible<T, Arg>::value)
2250 typename T = lib::type_pack_element_t<I, Ts...>,
2251 lib::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
2252 inline explicit constexpr
variant(
2254 Args &&... args) noexcept(std::is_nothrow_constructible<T,
2262 typename T = lib::type_pack_element_t<I, Ts...>,
2263 lib::enable_if_t<std::is_constructible<T,
2264 std::initializer_list<Up> &,
2267 inline explicit constexpr
variant(
2269 std::initializer_list<Up> il,
2270 Args &&... args) noexcept(
std::
2271 is_nothrow_constructible<
2273 std::initializer_list<Up> &,
2280 std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2281 lib::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
2282 inline explicit constexpr
variant(
2284 Args &&... args) noexcept(std::is_nothrow_constructible<T,
2292 std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2293 lib::enable_if_t<std::is_constructible<T,
2294 std::initializer_list<Up> &,
2297 inline explicit constexpr
variant(
2299 std::initializer_list<Up> il,
2300 Args &&... args) noexcept(
std::
2301 is_nothrow_constructible<
2303 std::initializer_list<Up> &,
2312 template <
typename Arg,
2313 lib::enable_if_t<!std::is_same<lib::decay_t<Arg>,
variant>::value,
2315 std::size_t I = detail::best_match<Arg, Ts...>::value,
2316 typename T = lib::type_pack_element_t<I, Ts...>,
2317 lib::enable_if_t<(std::is_assignable<T &, Arg>::value &&
2318 std::is_constructible<T, Arg>::value),
2320 inline variant &
operator=(Arg &&arg) noexcept(
2321 (std::is_nothrow_assignable<T &, Arg>::value &&
2322 std::is_nothrow_constructible<T, Arg>::value)) {
2323 impl_.template assign<I>(lib::forward<Arg>(arg));
2330 typename T = lib::type_pack_element_t<I, Ts...>,
2331 lib::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
2332 inline T &emplace(Args &&... args) {
2333 return impl_.template emplace<I>(lib::forward<Args>(args)...);
2340 typename T = lib::type_pack_element_t<I, Ts...>,
2341 lib::enable_if_t<std::is_constructible<T,
2342 std::initializer_list<Up> &,
2345 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
2346 return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
2352 std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2353 lib::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
2354 inline T &emplace(Args &&... args) {
2355 return impl_.template emplace<I>(lib::forward<Args>(args)...);
2362 std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2363 lib::enable_if_t<std::is_constructible<T,
2364 std::initializer_list<Up> &,
2367 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
2368 return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
2371 inline constexpr
bool valueless_by_exception()
const noexcept {
2372 return impl_.valueless_by_exception();
2375 inline constexpr std::size_t index()
const noexcept {
2376 return impl_.index();
2379 template <
bool Dummy =
true,
2385 Dummy>::value)...>::value,
2387 inline void swap(
variant &that) noexcept(
2388 lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
2389 lib::is_nothrow_swappable<Ts>::value)...>::value) {
2390 impl_.swap(that.impl_);
2400 template <std::size_t I,
typename... Ts>
2401 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
2402 return v.index() == I;
2405 template <
typename T,
typename... Ts>
2406 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
2407 return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);
2411 template <std::
size_t I,
typename V>
2415 constexpr AUTO_REFREF operator()(V &&v)
const
2417 access::variant::get_alt<I>(lib::forward<V>(v)).value)
2420 template <std::
size_t I,
typename V>
2421 inline constexpr AUTO_REFREF generic_get(V &&v)
2423 holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
2424 lib::forward<V>(v)))
2427 template <std::size_t I,
typename... Ts>
2428 inline constexpr variant_alternative_t<I,
variant<Ts...>> &get(
2430 return detail::generic_get<I>(v);
2433 template <std::size_t I,
typename... Ts>
2434 inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(
2435 variant<Ts...> &&v) {
2436 return detail::generic_get<I>(lib::move(v));
2439 template <std::size_t I,
typename... Ts>
2440 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &get(
2441 const variant<Ts...> &v) {
2442 return detail::generic_get<I>(v);
2445 template <std::size_t I,
typename... Ts>
2446 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &&get(
2447 const variant<Ts...> &&v) {
2448 return detail::generic_get<I>(lib::move(v));
2451 template <
typename T,
typename... Ts>
2452 inline constexpr T &get(variant<Ts...> &v) {
2453 return get<detail::find_index_checked<T, Ts...>::value>(v);
2456 template <
typename T,
typename... Ts>
2457 inline constexpr T &&get(variant<Ts...> &&v) {
2458 return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
2461 template <
typename T,
typename... Ts>
2462 inline constexpr
const T &get(
const variant<Ts...> &v) {
2463 return get<detail::find_index_checked<T, Ts...>::value>(v);
2466 template <
typename T,
typename... Ts>
2467 inline constexpr
const T &&get(
const variant<Ts...> &&v) {
2468 return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
2473 template <std::
size_t I,
typename V>
2474 inline constexpr AUTO generic_get_if(V *v) noexcept
2475 AUTO_RETURN(v && holds_alternative<I>(*v)
2476 ? lib::addressof(access::variant::get_alt<I>(*v).value)
2481 template <std::size_t I,
typename... Ts>
2482 inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
2483 get_if(variant<Ts...> *v) noexcept {
2484 return detail::generic_get_if<I>(v);
2487 template <std::size_t I,
typename... Ts>
2488 inline constexpr lib::add_pointer_t<
2489 const variant_alternative_t<I, variant<Ts...>>>
2490 get_if(
const variant<Ts...> *v) noexcept {
2491 return detail::generic_get_if<I>(v);
2494 template <
typename T,
typename... Ts>
2495 inline constexpr lib::add_pointer_t<T>
2496 get_if(variant<Ts...> *v) noexcept {
2497 return get_if<detail::find_index_checked<T, Ts...>::value>(v);
2500 template <
typename T,
typename... Ts>
2501 inline constexpr lib::add_pointer_t<const T>
2502 get_if(
const variant<Ts...> *v) noexcept {
2503 return get_if<detail::find_index_checked<T, Ts...>::value>(v);
2507 template <
typename RelOp>
2509 template <
typename Lhs,
typename Rhs>
2510 inline constexpr
bool operator()(Lhs &&lhs, Rhs &&rhs)
const {
2511 static_assert(std::is_convertible<lib::invoke_result_t<RelOp, Lhs, Rhs>,
2513 "relational operators must return a type"
2514 " implicitly convertible to bool");
2516 RelOp{}, lib::forward<Lhs>(lhs), lib::forward<Rhs>(rhs));
2521 template <
typename... Ts>
2526 #ifdef MPARK_CPP14_CONSTEXPR
2527 if (lhs.index() != rhs.index())
return false;
2528 if (lhs.valueless_by_exception())
return true;
2529 return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
2531 return lhs.index() == rhs.index() &&
2532 (lhs.valueless_by_exception() ||
2533 variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
2537 template <
typename... Ts>
2538 inline constexpr
bool operator!=(
const variant<Ts...> &lhs,
2539 const variant<Ts...> &rhs) {
2540 using detail::visitation::variant;
2541 using not_equal_to = detail::convert_to_bool<lib::not_equal_to>;
2542 #ifdef MPARK_CPP14_CONSTEXPR
2543 if (lhs.index() != rhs.index())
return true;
2544 if (lhs.valueless_by_exception())
return false;
2545 return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
2547 return lhs.index() != rhs.index() ||
2548 (!lhs.valueless_by_exception() &&
2549 variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
2553 template <
typename... Ts>
2554 inline constexpr
bool operator<(
const variant<Ts...> &lhs,
2555 const variant<Ts...> &rhs) {
2556 using detail::visitation::variant;
2557 using less = detail::convert_to_bool<lib::less>;
2558 #ifdef MPARK_CPP14_CONSTEXPR
2559 if (rhs.valueless_by_exception())
return false;
2560 if (lhs.valueless_by_exception())
return true;
2561 if (lhs.index() < rhs.index())
return true;
2562 if (lhs.index() > rhs.index())
return false;
2563 return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
2565 return !rhs.valueless_by_exception() &&
2566 (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||
2567 (lhs.index() == rhs.index() &&
2568 variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));
2572 template <
typename... Ts>
2573 inline constexpr
bool operator>(
const variant<Ts...> &lhs,
2574 const variant<Ts...> &rhs) {
2575 using detail::visitation::variant;
2576 using greater = detail::convert_to_bool<lib::greater>;
2577 #ifdef MPARK_CPP14_CONSTEXPR
2578 if (lhs.valueless_by_exception())
return false;
2579 if (rhs.valueless_by_exception())
return true;
2580 if (lhs.index() > rhs.index())
return true;
2581 if (lhs.index() < rhs.index())
return false;
2582 return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
2584 return !lhs.valueless_by_exception() &&
2585 (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||
2586 (lhs.index() == rhs.index() &&
2587 variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));
2591 template <
typename... Ts>
2592 inline constexpr
bool operator<=(
const variant<Ts...> &lhs,
2593 const variant<Ts...> &rhs) {
2594 using detail::visitation::variant;
2595 using less_equal = detail::convert_to_bool<lib::less_equal>;
2596 #ifdef MPARK_CPP14_CONSTEXPR
2597 if (lhs.valueless_by_exception())
return true;
2598 if (rhs.valueless_by_exception())
return false;
2599 if (lhs.index() < rhs.index())
return true;
2600 if (lhs.index() > rhs.index())
return false;
2601 return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
2603 return lhs.valueless_by_exception() ||
2604 (!rhs.valueless_by_exception() &&
2605 (lhs.index() < rhs.index() ||
2606 (lhs.index() == rhs.index() &&
2607 variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));
2611 template <
typename... Ts>
2612 inline constexpr
bool operator>=(
const variant<Ts...> &lhs,
2613 const variant<Ts...> &rhs) {
2614 using detail::visitation::variant;
2615 using greater_equal = detail::convert_to_bool<lib::greater_equal>;
2616 #ifdef MPARK_CPP14_CONSTEXPR
2617 if (rhs.valueless_by_exception())
return true;
2618 if (lhs.valueless_by_exception())
return false;
2619 if (lhs.index() > rhs.index())
return true;
2620 if (lhs.index() < rhs.index())
return false;
2621 return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
2623 return rhs.valueless_by_exception() ||
2624 (!lhs.valueless_by_exception() &&
2625 (lhs.index() > rhs.index() ||
2626 (lhs.index() == rhs.index() &&
2627 variant::visit_value_at(
2628 lhs.index(), greater_equal{}, lhs, rhs))));
2638 inline constexpr
bool operator>(monostate, monostate) noexcept {
2642 inline constexpr
bool operator<=(monostate, monostate) noexcept {
2646 inline constexpr
bool operator>=(monostate, monostate) noexcept {
2650 inline constexpr
bool operator==(monostate, monostate) noexcept {
2654 inline constexpr
bool operator!=(monostate, monostate) noexcept {
2658 #ifdef MPARK_CPP14_CONSTEXPR
2661 inline constexpr
bool all(std::initializer_list<bool> bs) {
2672 template <
typename Visitor,
typename... Vs>
2673 inline constexpr decltype(
auto) visit(Visitor &&visitor, Vs &&... vs) {
2674 return (detail::all({!vs.valueless_by_exception()...})
2676 : throw_bad_variant_access()),
2677 detail::visitation::variant::visit_value(
2678 lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
2683 template <std::
size_t N>
2684 inline constexpr
bool all_impl(
const lib::array<bool, N> &bs,
2686 return idx >= N || (bs[idx] && all_impl(bs, idx + 1));
2689 template <std::
size_t N>
2690 inline constexpr
bool all(
const lib::array<bool, N> &bs) {
2691 return all_impl(bs, 0);
2696 template <
typename Visitor,
typename... Vs>
2697 inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)
2698 DECLTYPE_AUTO_RETURN(
2700 lib::array<
bool,
sizeof...(Vs)>{{!vs.valueless_by_exception()...}})
2702 : throw_bad_variant_access()),
2703 detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
2704 lib::forward<Vs>(vs)...))
2707 template <
typename... Ts>
2708 inline auto swap(variant<Ts...> &lhs,
2709 variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
2710 -> decltype(lhs.swap(rhs)) {
2716 template <
typename T,
typename...>
2717 using enabled_type = T;
2721 template <
typename H,
typename K>
2722 constexpr
bool meets_requirements() noexcept {
2723 return std::is_copy_constructible<H>::value &&
2724 std::is_move_constructible<H>::value &&
2725 lib::is_invocable_r<std::size_t, H, const K &>::value;
2728 template <
typename K>
2729 constexpr
bool is_enabled() noexcept {
2730 using H = std::hash<K>;
2731 return meets_requirements<H, K>() &&
2732 std::is_default_constructible<H>::value &&
2733 std::is_copy_assignable<H>::value &&
2734 std::is_move_assignable<H>::value;
2745 #undef AUTO_REFREF_RETURN
2747 #undef DECLTYPE_AUTO
2748 #undef DECLTYPE_AUTO_RETURN
2754 template <
typename... Ts>
2755 struct hash<
smlt::detail::enabled_type<
2756 smlt::variant<Ts...>,
2757 smlt::lib::enable_if_t<smlt::lib::all<smlt::detail::hash::is_enabled<
2758 smlt::lib::remove_const_t<Ts>>()...>::value>>> {
2760 using result_type = std::size_t;
2762 inline result_type operator()(
const argument_type &v)
const {
2764 std::size_t result =
2765 v.valueless_by_exception()
2767 : variant::visit_alt(
2768 #ifdef MPARK_GENERIC_LAMBDAS
2769 [](
const auto &alt) {
2770 using alt_type = smlt::lib::decay_t<decltype(alt)>;
2771 using value_type = smlt::lib::remove_const_t<
2772 typename alt_type::value_type>;
2773 return hash<value_type>{}(alt.value);
2780 return hash_combine(result, hash<std::size_t>{}(v.index()));
2784 #ifndef MPARK_GENERIC_LAMBDAS
2786 template <
typename Alt>
2787 inline std::size_t operator()(
const Alt &alt)
const {
2788 using alt_type = smlt::lib::decay_t<Alt>;
2790 smlt::lib::remove_const_t<typename alt_type::value_type>;
2791 return hash<value_type>{}(alt.value);
2796 static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
2797 return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
2804 using result_type = std::size_t;
2806 inline result_type operator()(
const argument_type &)
const noexcept {
2813 #endif // MPARK_VARIANT_HPP