19 #ifndef GUL14_VARIANT_H_
20 #define GUL14_VARIANT_H_
25 #include <initializer_list>
28 #include <type_traits>
51 virtual const char* what()
const noexcept
override
53 return "bad_variant_access";
70 template <
typename... Ts>
89 template <
typename Visitor,
typename... Variants>
90 inline constexpr decltype(
auto)
visit(Visitor&& visitor_fct, Variants&&... variants);
103 template <typename Fct1, typename... Fcts>
106 using Fct1::operator();
115 template <
typename Fct1>
118 using Fct1::operator();
137 template <
typename... Fct>
149 #ifndef __has_attribute
150 #define __has_attribute(x) 0
153 #ifndef __has_builtin
154 #define __has_builtin(x) 0
157 #if __has_attribute(always_inline) || defined(__GNUC__)
158 #define GUL14_ALWAYS_INLINE __attribute__((__always_inline__)) inline
159 #elif defined(_MSC_VER)
160 #define GUL14_ALWAYS_INLINE __forceinline
162 #define GUL14_ALWAYS_INLINE inline
165 #if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
166 #define GUL14_BUILTIN_UNREACHABLE __builtin_unreachable()
167 #elif defined(_MSC_VER)
168 #define GUL14_BUILTIN_UNREACHABLE __assume(false)
170 #define GUL14_BUILTIN_UNREACHABLE
173 #define GUL14_RETURN(...) \
174 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
177 namespace detail_variant {
179 template <std::
size_t I,
typename T>
180 struct indexed_type : std::integral_constant<std::size_t, I> {
using type = T; };
182 template <
typename T, std::
size_t N>
184 constexpr
const T &operator[](std::size_t index)
const {
return data[index]; }
185 T data[N == 0 ? 1 : N];
188 template <
typename T,
bool>
189 struct dependent_type : T {};
191 template <
typename Is, std::
size_t J>
194 template <
typename Is, std::
size_t J>
195 using push_back_t =
typename push_back<Is, J>::type;
197 template <std::size_t... Is, std::size_t J>
198 struct push_back<std::index_sequence<Is...>, J> {
199 using type = std::index_sequence<Is..., J>;
202 #if __has_builtin(__type_pack_element) && !(defined(__ICC))
203 template <std::size_t I,
typename... Ts>
204 using type_pack_element_t = __type_pack_element<I, Ts...>;
206 template <std::size_t I,
typename... Ts>
207 struct type_pack_element_impl {
212 template <std::size_t... Is>
213 struct set<std::index_sequence<Is...>> : indexed_type<Is, Ts>... {};
215 template <
typename T>
216 inline static std::enable_if<true, T> impl(indexed_type<I, T>);
218 inline static std::enable_if<false> impl(...);
221 using type = decltype(impl(set<std::index_sequence_for<Ts...>>{}));
224 template <std::size_t I,
typename... Ts>
225 using type_pack_element =
typename type_pack_element_impl<I, Ts...>::type;
227 template <std::size_t I,
typename... Ts>
228 using type_pack_element_t =
typename type_pack_element<I, Ts...>::type;
231 template <
typename T>
232 struct identity {
using type = T; };
234 template <
bool... Bs>
235 using all = std::is_same<std::integer_sequence<bool,
true, Bs...>,
236 std::integer_sequence<bool, Bs...,
true>>;
238 template <
typename T>
239 struct is_reference_wrapper : std::false_type {};
241 template <
typename T>
242 struct is_reference_wrapper<std::reference_wrapper<T>>
248 #if __cplusplus >= 201703L
251 using std::invoke_result;
252 using std::invoke_result_t;
253 using std::is_invocable;
254 using std::is_invocable_r;
258 namespace detail_invoke {
264 struct Invoke<true , 0 > {
265 template <
typename R,
typename T,
typename Arg,
typename... Args>
266 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
267 GUL14_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
271 struct Invoke<true , 1 > {
272 template <
typename R,
typename T,
typename Arg,
typename... Args>
273 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
274 GUL14_RETURN((std::forward<Arg>(arg).
get().*pmf)(std::forward<Args>(args)...))
278 struct Invoke<true , 2 > {
279 template <
typename R,
typename T,
typename Arg,
typename... Args>
280 inline static constexpr
auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
281 GUL14_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
285 struct Invoke<false , 0 > {
286 template <
typename R,
typename T,
typename Arg>
287 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
288 GUL14_RETURN(std::forward<Arg>(arg).*pmo)
292 struct Invoke<false , 1 > {
293 template <
typename R,
typename T,
typename Arg>
294 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
295 GUL14_RETURN(std::forward<Arg>(arg).
get().*pmo)
299 struct Invoke<false , 2 > {
300 template <
typename R,
typename T,
typename Arg>
301 inline static constexpr
auto invoke(R T::*pmo, Arg &&arg)
302 GUL14_RETURN((*std::forward<Arg>(arg)).*pmo)
305 template <
typename R,
typename T,
typename Arg,
typename... Args>
306 inline constexpr
auto invoke(R T::*f, Arg &&arg, Args &&... args)
308 Invoke<std::is_function<R>::value,
309 (std::is_base_of<T, std::decay_t<Arg>>::value
311 : is_reference_wrapper<std::decay_t<Arg>>::value
314 std::forward<Arg>(arg),
315 std::forward<Args>(args)...))
318 #pragma warning(push)
319 #pragma warning(disable : 4100)
321 template <
typename F,
typename... Args>
322 inline constexpr
auto invoke(F &&f, Args &&... args)
323 GUL14_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
330 template <
typename F,
typename... Args>
331 inline constexpr
auto invoke(F &&f, Args &&... args)
332 GUL14_RETURN(detail_invoke::invoke(std::forward<F>(f), std::forward<Args>(args)...))
335 namespace detail_invoke_result {
337 template <
typename Void,
typename,
typename...>
338 struct invoke_result {};
340 template <
typename F,
typename... Args>
341 struct invoke_result<
void_t<decltype(invoke(
342 std::declval<F>(), std::declval<Args>()...))>,
346 invoke(std::declval<F>(), std::declval<Args>()...))> {};
350 template <
typename F,
typename... Args>
351 using invoke_result = detail_invoke_result::invoke_result<void, F, Args...>;
353 template <
typename F,
typename... Args>
354 using invoke_result_t =
typename invoke_result<F, Args...>::type;
357 namespace detail_invocable {
359 template <
typename Void,
typename,
typename...>
360 struct is_invocable : std::false_type {};
362 template <
typename F,
typename... Args>
363 struct is_invocable<
void_t<invoke_result_t<F, Args...>>, F, Args...>
366 template <
typename Void,
typename,
typename,
typename...>
367 struct is_invocable_r : std::false_type {};
369 template <
typename R,
typename F,
typename... Args>
370 struct is_invocable_r<
void_t<invoke_result_t<F, Args...>>,
374 : std::is_convertible<invoke_result_t<F, Args...>, R> {};
378 template <
typename F,
typename... Args>
379 using is_invocable = detail_invocable::is_invocable<void, F, Args...>;
381 template <
typename R,
typename F,
typename... Args>
382 using is_invocable_r = detail_invocable::is_invocable_r<void, R, F, Args...>;
387 namespace detail_swappable {
391 template <
typename T>
392 struct is_swappable {
394 template <
typename U,
395 typename = decltype(
swap(std::declval<U &>(),
396 std::declval<U &>()))>
397 inline static std::true_type test(
int);
399 template <
typename U>
400 inline static std::false_type test(...);
403 static constexpr
bool value = decltype(test<T>(0))::value;
406 template <
bool IsSwappable,
typename T>
407 struct is_nothrow_swappable {
408 static constexpr
bool value =
409 noexcept(
swap(std::declval<T &>(), std::declval<T &>()));
412 template <
typename T>
413 struct is_nothrow_swappable<false, T> : std::false_type {};
417 using detail_swappable::is_swappable;
419 template <
typename T>
420 using is_nothrow_swappable =
421 detail_swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
425 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
427 [[noreturn]]
inline void throw_bad_variant_access() {
428 throw bad_variant_access{};
431 template <
typename T>
434 template <
typename T>
435 constexpr std::size_t variant_size_v = variant_size<T>::value;
437 template <
typename T>
438 struct variant_size<const T> : variant_size<T> {};
440 template <
typename T>
441 struct variant_size<volatile T> : variant_size<T> {};
443 template <
typename T>
444 struct variant_size<const volatile T> : variant_size<T> {};
446 template <
typename... Ts>
447 struct variant_size<variant<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {};
449 template <std::
size_t I,
typename T>
450 struct variant_alternative;
452 template <std::
size_t I,
typename T>
453 using variant_alternative_t =
typename variant_alternative<I, T>::type;
455 template <std::
size_t I,
typename T>
456 struct variant_alternative<I, const T>
457 : std::add_const<variant_alternative_t<I, T>> {};
459 template <std::
size_t I,
typename T>
460 struct variant_alternative<I, volatile T>
461 : std::add_volatile<variant_alternative_t<I, T>> {};
463 template <std::
size_t I,
typename T>
464 struct variant_alternative<I, const volatile T>
465 : std::add_cv<variant_alternative_t<I, T>> {};
467 template <std::size_t I,
typename... Ts>
468 struct variant_alternative<I, variant<Ts...>> {
469 static_assert(I <
sizeof...(Ts),
470 "index out of bounds in `std::variant_alternative<>`");
471 using type =
typename detail_variant::type_pack_element_t<I, Ts...>;
474 constexpr std::size_t variant_npos =
static_cast<std::size_t
>(-1);
476 namespace detail_variant {
478 constexpr std::size_t not_found =
static_cast<std::size_t
>(-1);
479 constexpr std::size_t ambiguous =
static_cast<std::size_t
>(-2);
481 template <
typename T,
typename... Ts>
482 inline constexpr std::size_t find_index() {
483 constexpr detail_variant::array<bool,
sizeof...(Ts)> matches = {
484 {std::is_same<T, Ts>::value...}
486 std::size_t result = not_found;
487 for (std::size_t i = 0; i <
sizeof...(Ts); ++i) {
489 if (result != not_found) {
498 template <std::
size_t I>
499 using find_index_sfinae_impl =
500 std::enable_if_t<I != not_found && I != ambiguous,
501 std::integral_constant<std::size_t, I>>;
503 template <
typename T,
typename... Ts>
504 using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
506 template <std::
size_t I>
507 struct find_index_checked_impl : std::integral_constant<std::size_t, I> {
508 static_assert(I != not_found,
"the specified type is not found.");
509 static_assert(I != ambiguous,
"the specified type is ambiguous.");
512 template <
typename T,
typename... Ts>
513 using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
515 struct valueless_t {};
517 enum class Trait { TriviallyAvailable, Available, Unavailable };
519 template <
typename T,
520 template <
typename>
class IsTriviallyAvailable,
521 template <
typename>
class IsAvailable>
522 inline constexpr Trait trait() {
523 return IsTriviallyAvailable<T>::value
524 ? Trait::TriviallyAvailable
525 : IsAvailable<T>::value ? Trait::Available
526 : Trait::Unavailable;
529 template <
typename... Traits>
530 inline constexpr Trait common_trait(Traits... traits_) {
531 Trait result = Trait::TriviallyAvailable;
532 detail_variant::array<Trait,
sizeof...(Traits)> traits = {{traits_...}};
533 for (std::size_t i = 0; i <
sizeof...(Traits); ++i) {
535 if (
static_cast<int>(t) >
static_cast<int>(result)) {
542 template <
typename... Ts>
544 static constexpr Trait copy_constructible_trait =
545 common_trait(trait<Ts,
546 std::is_trivially_copy_constructible,
547 std::is_copy_constructible>()...);
549 static constexpr Trait move_constructible_trait =
550 common_trait(trait<Ts,
551 std::is_trivially_move_constructible,
552 std::is_move_constructible>()...);
554 static constexpr Trait copy_assignable_trait =
555 common_trait(copy_constructible_trait,
557 std::is_trivially_copy_assignable,
558 std::is_copy_assignable>()...);
560 static constexpr Trait move_assignable_trait =
561 common_trait(move_constructible_trait,
563 std::is_trivially_move_assignable,
564 std::is_move_assignable>()...);
566 static constexpr Trait destructible_trait =
567 common_trait(trait<Ts,
568 std::is_trivially_destructible,
569 std::is_destructible>()...);
574 struct recursive_union {
575 template <
typename V>
576 inline static constexpr
auto &&get_alt(V &&v, in_place_index_t<0>) {
577 return std::forward<V>(v).head_;
580 template <
typename V, std::
size_t I>
581 inline static constexpr
auto &&get_alt(V &&v, in_place_index_t<I>) {
582 return get_alt(std::forward<V>(v).tail_, in_place_index_t<I - 1>{});
587 template <std::
size_t I,
typename V>
588 inline static constexpr
auto&& get_alt(V &&v)
590 AUTO_REFREF_RETURN(recursive_union::get_alt(
591 std::forward<V>(v).data_, in_place_index_t<I>{}))
593 AUTO_REFREF_RETURN(recursive_union::get_alt(
594 data(std::forward<V>(v)), in_place_index_t<I>{}))
599 template <std::
size_t I,
typename V>
600 inline static constexpr
auto&& get_alt(V &&v)
601 AUTO_REFREF_RETURN(base::get_alt<I>(std::forward<V>(v).impl_))
606 namespace visitation {
608 #if !defined(_MSC_VER)
609 #define GUL14_VARIANT_SWITCH_VISIT
613 template <
typename Visitor,
typename... Vs>
614 using dispatch_result_t = decltype(
615 invoke(std::declval<Visitor>(),
616 access::base::get_alt<0>(std::declval<Vs>())...));
618 template <
typename Expected>
620 template <
typename Actual>
621 inline static constexpr
bool but_got() {
622 return std::is_same<Expected, Actual>::value;
626 template <
typename Expected,
typename Actual>
627 struct visit_return_type_check {
629 expected<Expected>::template but_got<Actual>(),
630 "`visit` requires the visitor to have a single return type");
632 template <
typename Visitor,
typename... Alts>
633 inline static constexpr decltype(
auto)
634 invoke(Visitor &&visitor, Alts &&... alts)
636 return ::gul14::detail_variant::invoke(
637 std::forward<Visitor>(visitor), std::forward<Alts>(alts)...);
641 #ifdef GUL14_VARIANT_SWITCH_VISIT
642 template <
bool B,
typename R,
typename... ITs>
645 template <
typename R,
typename... ITs>
646 struct dispatcher<false, R, ITs...> {
647 template <std::size_t B,
typename F,
typename... Vs>
648 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
649 F &&,
typename ITs::type &&..., Vs &&...) {
650 GUL14_BUILTIN_UNREACHABLE;
653 template <std::size_t I,
typename F,
typename... Vs>
654 GUL14_ALWAYS_INLINE
static constexpr R dispatch_case(F &&, Vs &&...) {
655 GUL14_BUILTIN_UNREACHABLE;
658 template <std::size_t B,
typename F,
typename... Vs>
659 GUL14_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t,
662 GUL14_BUILTIN_UNREACHABLE;
666 template <
typename R,
typename... ITs>
667 struct dispatcher<true, R, ITs...> {
668 template <std::
size_t B,
typename F>
669 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
670 F &&f,
typename ITs::type &&... visited_vs) {
672 using Actual = decltype(invoke(
674 access::base::get_alt<ITs::value>(
675 std::forward<typename ITs::type>(visited_vs))...));
676 return visit_return_type_check<Expected, Actual>::invoke(
678 access::base::get_alt<ITs::value>(
679 std::forward<typename ITs::type>(visited_vs))...);
682 template <std::size_t B,
typename F,
typename V,
typename... Vs>
683 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
684 F &&f,
typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
685 #define GUL14_DISPATCH(I) \
686 dispatcher<(I < std::decay_t<V>::size()), \
689 detail_variant::indexed_type<I, V>>:: \
690 template dispatch<0>(std::forward<F>(f), \
691 std::forward<typename ITs::type>(visited_vs)..., \
692 std::forward<V>(v), \
693 std::forward<Vs>(vs)...)
695 #define GUL14_DEFAULT(I) \
696 dispatcher<(I < std::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
697 std::forward<F>(f), \
698 std::forward<typename ITs::type>(visited_vs)..., \
699 std::forward<V>(v), \
700 std::forward<Vs>(vs)...)
703 case B + 0:
return GUL14_DISPATCH(B + 0);
704 case B + 1:
return GUL14_DISPATCH(B + 1);
705 case B + 2:
return GUL14_DISPATCH(B + 2);
706 case B + 3:
return GUL14_DISPATCH(B + 3);
707 case B + 4:
return GUL14_DISPATCH(B + 4);
708 case B + 5:
return GUL14_DISPATCH(B + 5);
709 case B + 6:
return GUL14_DISPATCH(B + 6);
710 case B + 7:
return GUL14_DISPATCH(B + 7);
711 case B + 8:
return GUL14_DISPATCH(B + 8);
712 case B + 9:
return GUL14_DISPATCH(B + 9);
713 case B + 10:
return GUL14_DISPATCH(B + 10);
714 case B + 11:
return GUL14_DISPATCH(B + 11);
715 case B + 12:
return GUL14_DISPATCH(B + 12);
716 case B + 13:
return GUL14_DISPATCH(B + 13);
717 case B + 14:
return GUL14_DISPATCH(B + 14);
718 case B + 15:
return GUL14_DISPATCH(B + 15);
719 case B + 16:
return GUL14_DISPATCH(B + 16);
720 case B + 17:
return GUL14_DISPATCH(B + 17);
721 case B + 18:
return GUL14_DISPATCH(B + 18);
722 case B + 19:
return GUL14_DISPATCH(B + 19);
723 case B + 20:
return GUL14_DISPATCH(B + 20);
724 case B + 21:
return GUL14_DISPATCH(B + 21);
725 case B + 22:
return GUL14_DISPATCH(B + 22);
726 case B + 23:
return GUL14_DISPATCH(B + 23);
727 case B + 24:
return GUL14_DISPATCH(B + 24);
728 case B + 25:
return GUL14_DISPATCH(B + 25);
729 case B + 26:
return GUL14_DISPATCH(B + 26);
730 case B + 27:
return GUL14_DISPATCH(B + 27);
731 case B + 28:
return GUL14_DISPATCH(B + 28);
732 case B + 29:
return GUL14_DISPATCH(B + 29);
733 case B + 30:
return GUL14_DISPATCH(B + 30);
734 case B + 31:
return GUL14_DISPATCH(B + 31);
735 default:
return GUL14_DEFAULT(B + 32);
739 #undef GUL14_DISPATCH
742 template <std::size_t I,
typename F,
typename... Vs>
743 GUL14_ALWAYS_INLINE
static constexpr R dispatch_case(F &&f,
746 using Actual = decltype(
747 invoke(std::forward<F>(f),
748 access::base::get_alt<I>(std::forward<Vs>(vs))...));
749 return visit_return_type_check<Expected, Actual>::invoke(
751 access::base::get_alt<I>(std::forward<Vs>(vs))...);
754 template <std::size_t B,
typename F,
typename V,
typename... Vs>
755 GUL14_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t index,
759 static_assert(detail_variant::all<(std::decay_t<V>::size() ==
760 std::decay_t<Vs>::size())...>::value,
761 "all of the variants must be the same size.");
762 #define GUL14_DISPATCH_AT(I) \
763 dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_case<I>( \
764 std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
766 #define GUL14_DEFAULT(I) \
767 dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_at<I>( \
768 index, std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
771 case B + 0:
return GUL14_DISPATCH_AT(B + 0);
772 case B + 1:
return GUL14_DISPATCH_AT(B + 1);
773 case B + 2:
return GUL14_DISPATCH_AT(B + 2);
774 case B + 3:
return GUL14_DISPATCH_AT(B + 3);
775 case B + 4:
return GUL14_DISPATCH_AT(B + 4);
776 case B + 5:
return GUL14_DISPATCH_AT(B + 5);
777 case B + 6:
return GUL14_DISPATCH_AT(B + 6);
778 case B + 7:
return GUL14_DISPATCH_AT(B + 7);
779 case B + 8:
return GUL14_DISPATCH_AT(B + 8);
780 case B + 9:
return GUL14_DISPATCH_AT(B + 9);
781 case B + 10:
return GUL14_DISPATCH_AT(B + 10);
782 case B + 11:
return GUL14_DISPATCH_AT(B + 11);
783 case B + 12:
return GUL14_DISPATCH_AT(B + 12);
784 case B + 13:
return GUL14_DISPATCH_AT(B + 13);
785 case B + 14:
return GUL14_DISPATCH_AT(B + 14);
786 case B + 15:
return GUL14_DISPATCH_AT(B + 15);
787 case B + 16:
return GUL14_DISPATCH_AT(B + 16);
788 case B + 17:
return GUL14_DISPATCH_AT(B + 17);
789 case B + 18:
return GUL14_DISPATCH_AT(B + 18);
790 case B + 19:
return GUL14_DISPATCH_AT(B + 19);
791 case B + 20:
return GUL14_DISPATCH_AT(B + 20);
792 case B + 21:
return GUL14_DISPATCH_AT(B + 21);
793 case B + 22:
return GUL14_DISPATCH_AT(B + 22);
794 case B + 23:
return GUL14_DISPATCH_AT(B + 23);
795 case B + 24:
return GUL14_DISPATCH_AT(B + 24);
796 case B + 25:
return GUL14_DISPATCH_AT(B + 25);
797 case B + 26:
return GUL14_DISPATCH_AT(B + 26);
798 case B + 27:
return GUL14_DISPATCH_AT(B + 27);
799 case B + 28:
return GUL14_DISPATCH_AT(B + 28);
800 case B + 29:
return GUL14_DISPATCH_AT(B + 29);
801 case B + 30:
return GUL14_DISPATCH_AT(B + 30);
802 case B + 31:
return GUL14_DISPATCH_AT(B + 31);
803 default:
return GUL14_DEFAULT(B + 32);
807 #undef GUL14_DISPATCH_AT
811 template <
typename T>
812 inline static constexpr
const T &at(
const T &elem) noexcept {
816 template <
typename T, std::size_t N,
typename... Is>
817 inline static constexpr
const std::remove_all_extents_t<T> &at(
818 const detail_variant::array<T, N> &elems, std::size_t i, Is... is) noexcept {
819 return at(elems[i], is...);
822 template <
typename F,
typename... Fs>
823 inline static constexpr detail_variant::array<std::decay_t<F>,
sizeof...(Fs) + 1>
824 make_farray(F &&f, Fs &&... fs) {
825 return {{std::forward<F>(f), std::forward<Fs>(fs)...}};
828 template <
typename F,
typename... Vs>
829 struct make_fmatrix_impl {
831 template <std::size_t... Is>
832 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
833 F &&f, Vs &&... vs) {
834 using Expected = dispatch_result_t<F, Vs...>;
835 using Actual = decltype(invoke(
837 access::base::get_alt<Is>(std::forward<Vs>(vs))...));
838 return visit_return_type_check<Expected, Actual>::invoke(
840 access::base::get_alt<Is>(std::forward<Vs>(vs))...);
843 template <std::size_t... Is>
844 inline static constexpr
auto impl(std::index_sequence<Is...>) {
845 return &dispatch<Is...>;
848 template <
typename Is, std::size_t... Js,
typename... Ls>
849 inline static constexpr
auto impl(Is,
850 std::index_sequence<Js...>,
852 return make_farray(impl(detail_variant::push_back_t<Is, Js>{}, ls...)...);
856 template <
typename F,
typename... Vs>
857 inline static constexpr
auto make_fmatrix() {
858 return make_fmatrix_impl<F, Vs...>::impl(
859 std::index_sequence<>{},
860 std::make_index_sequence<std::decay_t<Vs>::size()>{}...);
863 template <
typename F,
typename... Vs>
864 struct make_fdiagonal_impl {
865 template <std::
size_t I>
866 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
867 F &&f, Vs &&... vs) {
868 using Expected = dispatch_result_t<F, Vs...>;
869 using Actual = decltype(
870 invoke(std::forward<F>(f),
871 access::base::get_alt<I>(std::forward<Vs>(vs))...));
872 return visit_return_type_check<Expected, Actual>::invoke(
874 access::base::get_alt<I>(std::forward<Vs>(vs))...);
877 template <std::size_t... Is>
878 inline static constexpr
auto impl(std::index_sequence<Is...>) {
879 return make_farray(&dispatch<Is>...);
883 template <
typename F,
typename V,
typename... Vs>
884 inline static constexpr
auto make_fdiagonal()
885 -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(
886 std::make_index_sequence<std::decay_t<V>::size()>{})) {
887 static_assert(detail_variant::all<(std::decay_t<V>::size() ==
888 std::decay_t<Vs>::size())...>::value,
889 "all of the variants must be the same size.");
890 return make_fdiagonal_impl<F, V, Vs...>::impl(
891 std::make_index_sequence<std::decay_t<V>::size()>{});
896 #if !defined(GUL14_VARIANT_SWITCH_VISIT) && \
897 (!defined(_MSC_VER) || _MSC_VER >= 1910)
898 template <
typename F,
typename... Vs>
899 using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
901 template <
typename F,
typename... Vs>
903 static constexpr fmatrix_t<F, Vs...> value =
904 base::make_fmatrix<F, Vs...>();
907 template <
typename F,
typename... Vs>
908 constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;
910 template <
typename F,
typename... Vs>
911 using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
913 template <
typename F,
typename... Vs>
915 static constexpr fdiagonal_t<F, Vs...> value =
916 base::make_fdiagonal<F, Vs...>();
919 template <
typename F,
typename... Vs>
920 constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;
924 template <
typename Visitor,
typename... Vs>
925 inline static constexpr decltype(
auto) visit_alt(Visitor &&visitor,
927 #ifdef GUL14_VARIANT_SWITCH_VISIT
929 return base::dispatcher<
931 base::dispatch_result_t<Visitor,
933 std::forward<Vs>(vs)))...>>::
934 template dispatch<0>(std::forward<Visitor>(visitor),
935 as_base(std::forward<Vs>(vs))...);
937 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
941 decltype(as_base(std::forward<Vs>(vs)))...>::value,
942 vs.index()...)(std::forward<Visitor>(visitor),
943 as_base(std::forward<Vs>(vs))...);
948 base::make_fmatrix<Visitor &&,
949 decltype(as_base(std::forward<Vs>(vs)))...>(),
950 vs.index()...)(std::forward<Visitor>(visitor),
951 as_base(std::forward<Vs>(vs))...);
955 template <
typename Visitor,
typename... Vs>
956 inline static constexpr decltype(
auto) visit_alt_at(std::
size_t index,
959 #ifdef GUL14_VARIANT_SWITCH_VISIT
961 return base::dispatcher<
963 base::dispatch_result_t<Visitor,
965 std::forward<Vs>(vs)))...>>::
966 template dispatch_at<0>(index,
967 std::forward<Visitor>(visitor),
968 as_base(std::forward<Vs>(vs))...);
970 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
973 fdiagonal<Visitor &&,
974 decltype(as_base(std::forward<Vs>(vs)))...>::value,
975 index)(std::forward<Visitor>(visitor),
976 as_base(std::forward<Vs>(vs))...);
981 base::make_fdiagonal<Visitor &&,
982 decltype(as_base(std::forward<Vs>(vs)))...>(),
983 index)(std::forward<Visitor>(visitor),
984 as_base(std::forward<Vs>(vs))...);
991 template <
typename Visitor>
993 template <
typename... Values>
994 inline static constexpr
bool does_not_handle() {
995 return detail_variant::is_invocable<Visitor, Values...>::value;
999 template <
typename Visitor,
typename... Values>
1000 struct visit_exhaustiveness_check {
1001 static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
1002 "`visit` requires the visitor to be exhaustive.");
1004 inline static constexpr decltype(
auto)
1005 invoke(Visitor &&visitor, Values &&... values)
1007 return detail_variant::invoke(std::forward<Visitor>(visitor),
1008 std::forward<Values>(values)...);
1012 template <
typename Visitor>
1013 struct value_visitor {
1016 template <
typename... Alts>
1017 inline constexpr decltype(
auto) operator()(Alts &&... alts)
const
1019 return visit_exhaustiveness_check<
1021 decltype((std::forward<Alts>(alts).value))...>::
1022 invoke(std::forward<Visitor>(visitor_),
1023 std::forward<Alts>(alts).value...);
1027 template <
typename Visitor>
1028 inline static constexpr
auto make_value_visitor(Visitor &&visitor) {
1029 return value_visitor<Visitor>{std::forward<Visitor>(visitor)};
1033 template <
typename Visitor,
typename... Vs>
1034 inline static constexpr decltype(
auto) visit_alt(Visitor &&visitor, Vs &&... vs)
1036 return alt::visit_alt(std::forward<Visitor>(visitor),
1037 std::forward<Vs>(vs).impl_...);
1040 template <
typename Visitor,
typename... Vs>
1041 inline static constexpr decltype(
auto) visit_alt_at(std::
size_t index,
1045 return alt::visit_alt_at(index, std::forward<Visitor>(visitor),
1046 std::forward<Vs>(vs).impl_...);
1049 template <
typename Visitor,
typename... Vs>
1050 inline static constexpr decltype(
auto) visit_value(Visitor &&visitor,
1053 return visit_alt(make_value_visitor(std::forward<Visitor>(visitor)),
1054 std::forward<Vs>(vs)...);
1057 template <
typename Visitor,
typename... Vs>
1058 inline static constexpr decltype(
auto) visit_value_at(std::
size_t index,
1062 return visit_alt_at(index, make_value_visitor(std::forward<Visitor>(visitor)),
1063 std::forward<Vs>(vs)...);
1069 template <std::
size_t Index,
typename T>
1071 using value_type = T;
1074 #pragma warning(push)
1075 #pragma warning(disable : 4244)
1077 template <
typename... Args>
1078 inline explicit constexpr alt(in_place_t, Args &&... args)
1079 : value(std::forward<Args>(args)...) {}
1081 #pragma warning(pop)
1087 template <Trait DestructibleTrait, std::size_t Index,
typename... Ts>
1088 union recursive_union;
1090 template <Trait DestructibleTrait, std::
size_t Index>
1091 union recursive_union<DestructibleTrait, Index> {};
1093 #define GUL14_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
1094 template <std::size_t Index, typename T, typename... Ts> \
1095 union recursive_union<destructible_trait, Index, T, Ts...> { \
1097 inline explicit constexpr recursive_union(valueless_t) noexcept \
1100 template <typename... Args> \
1101 inline explicit constexpr recursive_union(in_place_index_t<0>, \
1103 : head_(in_place_t{}, std::forward<Args>(args)...) {} \
1105 template <std::size_t I, typename... Args> \
1106 inline explicit constexpr recursive_union(in_place_index_t<I>, \
1108 : tail_(in_place_index_t<I - 1>{}, std::forward<Args>(args)...) {} \
1110 recursive_union(const recursive_union &) = default; \
1111 recursive_union(recursive_union &&) = default; \
1115 recursive_union &operator=(const recursive_union &) = default; \
1116 recursive_union &operator=(recursive_union &&) = default; \
1120 alt<Index, T> head_; \
1121 recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
1123 friend struct access::recursive_union; \
1126 GUL14_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
1127 ~recursive_union() =
default;);
1128 GUL14_VARIANT_RECURSIVE_UNION(Trait::Available,
1129 ~recursive_union() {});
1130 GUL14_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
1131 ~recursive_union() =
delete;);
1133 #undef GUL14_VARIANT_RECURSIVE_UNION
1135 template <
typename... Ts>
1136 using index_t =
typename std::conditional<
1137 sizeof...(Ts) < (std::numeric_limits<unsigned char>::max)(),
1139 typename std::conditional<
1140 sizeof...(Ts) < (std::numeric_limits<unsigned short>::max)(),
1145 template <Trait DestructibleTrait,
typename... Ts>
1148 inline explicit constexpr base(valueless_t tag) noexcept
1149 : data_(tag), index_(
static_cast<index_t<Ts...
>>(-1)) {}
1151 template <std::size_t I,
typename... Args>
1152 inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
1153 : data_(in_place_index_t<I>{}, std::forward<Args>(args)...),
1156 inline constexpr
bool valueless_by_exception() const noexcept {
1157 return index_ ==
static_cast<index_t<Ts...
>>(-1);
1160 inline constexpr std::size_t index() const noexcept {
1161 return valueless_by_exception() ? variant_npos : index_;
1165 using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
1167 friend inline constexpr base &as_base(base &b) {
return b; }
1168 friend inline constexpr
const base &as_base(
const base &b) {
return b; }
1169 friend inline constexpr base &&as_base(base &&b) {
return std::move(b); }
1170 friend inline constexpr
const base &&as_base(
const base &&b) {
return std::move(b); }
1172 friend inline constexpr data_t &data(base &b) {
return b.data_; }
1173 friend inline constexpr
const data_t &data(
const base &b) {
return b.data_; }
1174 friend inline constexpr data_t &&data(base &&b) {
return std::move(b).data_; }
1175 friend inline constexpr
const data_t &&data(
const base &&b) {
return std::move(b).data_; }
1177 inline static constexpr std::size_t size() {
return sizeof...(Ts); }
1180 index_t<Ts...> index_;
1182 friend struct access::base;
1183 friend struct visitation::base;
1188 #pragma warning(push)
1189 #pragma warning(disable : 4100)
1191 template <
typename Alt>
1192 inline void operator()(Alt &alt)
const noexcept { alt.~Alt(); }
1194 #pragma warning(pop)
1198 #if !defined(_MSC_VER) || _MSC_VER >= 1910
1199 #define GUL14_INHERITING_CTOR(type, base) using base::base;
1201 #define GUL14_INHERITING_CTOR(type, base) \
1202 template <typename... Args> \
1203 inline explicit constexpr type(Args &&... args) \
1204 : base(std::forward<Args>(args)...) {}
1207 template <
typename Traits, Trait = Traits::destructible_trait>
1210 #define GUL14_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
1211 template <typename... Ts> \
1212 class destructor<traits<Ts...>, destructible_trait> \
1213 : public base<destructible_trait, Ts...> { \
1214 using super = base<destructible_trait, Ts...>; \
1217 GUL14_INHERITING_CTOR(destructor, super) \
1218 using super::operator=; \
1220 destructor(const destructor &) = default; \
1221 destructor(destructor &&) = default; \
1223 destructor &operator=(const destructor &) = default; \
1224 destructor &operator=(destructor &&) = default; \
1230 GUL14_VARIANT_DESTRUCTOR(
1231 Trait::TriviallyAvailable,
1232 ~destructor() =
default;,
1233 inline void destroy() noexcept {
1234 this->index_ =
static_cast<index_t<Ts...
>>(-1);
1237 GUL14_VARIANT_DESTRUCTOR(
1239 ~destructor() { destroy(); },
1240 inline void destroy() noexcept {
1241 if (!this->valueless_by_exception()) {
1242 visitation::alt::visit_alt(dtor{}, *
this);
1244 this->index_ =
static_cast<index_t<Ts...
>>(-1);
1247 GUL14_VARIANT_DESTRUCTOR(
1249 ~destructor() =
delete;,
1250 inline void destroy() noexcept = delete;);
1252 #undef GUL14_VARIANT_DESTRUCTOR
1254 template <
typename Traits>
1255 class constructor :
public destructor<Traits> {
1256 using super = destructor<Traits>;
1259 GUL14_INHERITING_CTOR(constructor, super)
1260 using super::operator=;
1263 template <std::size_t I,
typename T,
typename... Args>
1264 inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
1265 auto *result = ::new (
static_cast<void *
>(std::addressof(a)))
1266 alt<I, T>(in_place_t{}, std::forward<Args>(args)...);
1267 return result->value;
1270 template <
typename Rhs>
1271 inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
1273 if (!rhs.valueless_by_exception()) {
1274 visitation::alt::visit_alt_at(
1276 [](
auto &lhs_alt,
auto &&rhs_alt) {
1277 constructor::construct_alt(
1278 lhs_alt, std::forward<decltype(rhs_alt)>(rhs_alt).value);
1282 std::forward<Rhs>(rhs));
1283 lhs.index_ = rhs.index_;
1288 template <
typename Traits, Trait = Traits::move_constructible_trait>
1289 class move_constructor;
1291 #define GUL14_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
1292 template <typename... Ts> \
1293 class move_constructor<traits<Ts...>, move_constructible_trait> \
1294 : public constructor<traits<Ts...>> { \
1295 using super = constructor<traits<Ts...>>; \
1298 GUL14_INHERITING_CTOR(move_constructor, super) \
1299 using super::operator=; \
1301 move_constructor(const move_constructor &) = default; \
1303 ~move_constructor() = default; \
1304 move_constructor &operator=(const move_constructor &) = default; \
1305 move_constructor &operator=(move_constructor &&) = default; \
1308 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1309 Trait::TriviallyAvailable,
1310 move_constructor(move_constructor &&that) =
default;);
1312 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1314 move_constructor(move_constructor &&that) noexcept(
1315 detail_variant::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
1316 : move_constructor(valueless_t{}) {
1317 this->generic_construct(*
this, std::move(that));
1320 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1322 move_constructor(move_constructor &&) =
delete;);
1324 #undef GUL14_VARIANT_MOVE_CONSTRUCTOR
1326 template <
typename Traits, Trait = Traits::copy_constructible_trait>
1327 class copy_constructor;
1329 #define GUL14_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
1330 template <typename... Ts> \
1331 class copy_constructor<traits<Ts...>, copy_constructible_trait> \
1332 : public move_constructor<traits<Ts...>> { \
1333 using super = move_constructor<traits<Ts...>>; \
1336 GUL14_INHERITING_CTOR(copy_constructor, super) \
1337 using super::operator=; \
1340 copy_constructor(copy_constructor &&) = default; \
1341 ~copy_constructor() = default; \
1342 copy_constructor &operator=(const copy_constructor &) = default; \
1343 copy_constructor &operator=(copy_constructor &&) = default; \
1346 GUL14_VARIANT_COPY_CONSTRUCTOR(
1347 Trait::TriviallyAvailable,
1348 copy_constructor(
const copy_constructor &that) =
default;);
1350 GUL14_VARIANT_COPY_CONSTRUCTOR(
1352 copy_constructor(
const copy_constructor &that)
1353 : copy_constructor(valueless_t{}) {
1354 this->generic_construct(*
this, that);
1357 GUL14_VARIANT_COPY_CONSTRUCTOR(
1359 copy_constructor(
const copy_constructor &) =
delete;);
1361 #undef GUL14_VARIANT_COPY_CONSTRUCTOR
1363 template <
typename Traits>
1364 class assignment :
public copy_constructor<Traits> {
1365 using super = copy_constructor<Traits>;
1368 GUL14_INHERITING_CTOR(assignment, super)
1369 using super::operator=;
1371 template <std::size_t I,
typename... Args>
1372 inline auto emplace(Args &&... args)
1373 -> decltype(this->construct_alt(access::base::get_alt<I>(*
this),
1374 std::forward<Args>(args)...)) {
1376 auto &result = this->construct_alt(access::base::get_alt<I>(*
this),
1377 std::forward<Args>(args)...);
1383 template <std::
size_t I,
typename T,
typename Arg>
1384 inline void assign_alt(alt<I, T> &a, Arg &&arg) {
1385 if (this->index() == I) {
1387 #pragma warning(push)
1388 #pragma warning(disable : 4244)
1390 a.value = std::forward<Arg>(arg);
1392 #pragma warning(pop)
1396 void operator()(std::true_type)
const {
1397 this_->emplace<I>(std::forward<Arg>(arg_));
1399 void operator()(std::false_type)
const {
1400 this_->emplace<I>(T(std::forward<Arg>(arg_)));
1404 } impl{
this, std::forward<Arg>(arg)};
1405 impl(std::integral_constant<
bool,
1406 std::is_nothrow_constructible<T, Arg>::value ||
1407 !std::is_nothrow_move_constructible<T>::value>{});
1411 template <
typename That>
1412 inline void generic_assign(That &&that) {
1413 if (this->valueless_by_exception() && that.valueless_by_exception()) {
1415 }
else if (that.valueless_by_exception()) {
1418 visitation::alt::visit_alt_at(
1420 [
this](
auto &this_alt,
auto &&that_alt) {
1422 this_alt, std::forward<decltype(that_alt)>(that_alt).value);
1425 std::forward<That>(that));
1430 template <
typename Traits, Trait = Traits::move_assignable_trait>
1431 class move_assignment;
1433 #define GUL14_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
1434 template <typename... Ts> \
1435 class move_assignment<traits<Ts...>, move_assignable_trait> \
1436 : public assignment<traits<Ts...>> { \
1437 using super = assignment<traits<Ts...>>; \
1440 GUL14_INHERITING_CTOR(move_assignment, super) \
1441 using super::operator=; \
1443 move_assignment(const move_assignment &) = default; \
1444 move_assignment(move_assignment &&) = default; \
1445 ~move_assignment() = default; \
1446 move_assignment &operator=(const move_assignment &) = default; \
1450 GUL14_VARIANT_MOVE_ASSIGNMENT(
1451 Trait::TriviallyAvailable,
1452 move_assignment &
operator=(move_assignment &&that) =
default;);
1454 GUL14_VARIANT_MOVE_ASSIGNMENT(
1457 operator=(move_assignment &&that) noexcept(
1458 detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1459 std::is_nothrow_move_assignable<Ts>::value)...>::value) {
1460 this->generic_assign(std::move(that));
1464 GUL14_VARIANT_MOVE_ASSIGNMENT(
1466 move_assignment &
operator=(move_assignment &&) =
delete;);
1468 #undef GUL14_VARIANT_MOVE_ASSIGNMENT
1470 template <
typename Traits, Trait = Traits::copy_assignable_trait>
1471 class copy_assignment;
1473 #define GUL14_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
1474 template <typename... Ts> \
1475 class copy_assignment<traits<Ts...>, copy_assignable_trait> \
1476 : public move_assignment<traits<Ts...>> { \
1477 using super = move_assignment<traits<Ts...>>; \
1480 GUL14_INHERITING_CTOR(copy_assignment, super) \
1481 using super::operator=; \
1483 copy_assignment(const copy_assignment &) = default; \
1484 copy_assignment(copy_assignment &&) = default; \
1485 ~copy_assignment() = default; \
1487 copy_assignment &operator=(copy_assignment &&) = default; \
1490 GUL14_VARIANT_COPY_ASSIGNMENT(
1491 Trait::TriviallyAvailable,
1492 copy_assignment &
operator=(
const copy_assignment &that) =
default;);
1494 GUL14_VARIANT_COPY_ASSIGNMENT(
1496 copy_assignment &
operator=(
const copy_assignment &that) {
1497 this->generic_assign(that);
1501 GUL14_VARIANT_COPY_ASSIGNMENT(
1503 copy_assignment &
operator=(
const copy_assignment &) =
delete;);
1505 #undef GUL14_VARIANT_COPY_ASSIGNMENT
1507 template <
typename... Ts>
1508 class impl :
public copy_assignment<traits<Ts...>> {
1509 using super = copy_assignment<traits<Ts...>>;
1512 GUL14_INHERITING_CTOR(impl, super)
1513 using super::operator=;
1515 impl(
const impl&) =
default;
1516 impl(impl&&) =
default;
1518 impl &operator=(
const impl &) =
default;
1519 impl &operator=(impl &&) =
default;
1521 template <std::
size_t I,
typename Arg>
1522 inline void assign(Arg &&arg) {
1523 this->assign_alt(access::base::get_alt<I>(*
this),
1524 std::forward<Arg>(arg));
1527 inline void swap(impl &that) {
1528 if (this->valueless_by_exception() && that.valueless_by_exception()) {
1530 }
else if (this->index() == that.index()) {
1531 visitation::alt::visit_alt_at(this->index(),
1532 [](
auto &this_alt,
auto &that_alt) {
1534 swap(this_alt.value,
1541 impl *rhs = std::addressof(that);
1542 if (lhs->move_nothrow() && !rhs->move_nothrow()) {
1545 impl tmp(std::move(*rhs));
1550 this->generic_construct(*rhs, std::move(*lhs));
1552 if (tmp.move_nothrow()) {
1553 this->generic_construct(*rhs, std::move(tmp));
1557 this->generic_construct(*lhs, std::move(tmp));
1562 inline constexpr
bool move_nothrow()
const {
1563 return this->valueless_by_exception() ||
1564 detail_variant::array<bool,
sizeof...(Ts)>{
1565 {std::is_nothrow_move_constructible<Ts>::value...}
1570 #undef GUL14_INHERITING_CTOR
1572 template <
typename From,
typename To>
1573 struct is_non_narrowing_convertible {
1574 template <
typename T>
1575 static std::true_type test(T(&&)[1]);
1577 template <
typename T>
1578 static auto impl(
int) -> decltype(test<T>({std::declval<From>()}));
1581 static auto impl(...) -> std::false_type;
1583 static constexpr
bool value = decltype(impl<To>(0))::value;
1586 template <
typename Arg,
1589 bool = std::is_arithmetic<T>::value,
1591 struct overload_leaf {};
1593 template <
typename Arg, std::
size_t I,
typename T>
1594 struct overload_leaf<Arg, I, T, false> {
1595 using impl = std::integral_constant<std::size_t, I> (*)(T);
1596 operator impl()
const {
return nullptr; };
1599 template <
typename Arg, std::
size_t I,
typename T>
1600 struct overload_leaf<
1605 #if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
1608 std::is_same<remove_cvref_t<T>,
bool>::value
1609 ? std::is_same<remove_cvref_t<Arg>,
bool>::value
1610 : is_non_narrowing_convertible<Arg, T>::value>
1613 using impl = std::integral_constant<std::size_t, I> (*)(T);
1614 operator impl()
const {
return nullptr; };
1617 template <
typename Arg,
typename... Ts>
1618 struct overload_impl {
1623 template <std::size_t... Is>
1624 struct impl<std::index_sequence<Is...>> : overload_leaf<Arg, Is, Ts>... {};
1627 using type = impl<std::index_sequence_for<Ts...>>;
1630 template <
typename Arg,
typename... Ts>
1631 using overload =
typename overload_impl<Arg, Ts...>::type;
1633 template <
typename Arg,
typename... Ts>
1634 using best_match = invoke_result_t<overload<Arg, Ts...>, Arg>;
1636 template <
typename T>
1637 struct is_in_place_index : std::false_type {};
1639 template <std::
size_t I>
1640 struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
1642 template <
typename T>
1643 struct is_in_place_type : std::false_type {};
1645 template <
typename T>
1646 struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
1650 template <
typename... Ts>
1652 static_assert(0 <
sizeof...(Ts),
1653 "variant must consist of at least one alternative.");
1655 static_assert(detail_variant::all<!std::is_array<Ts>::value...>::value,
1656 "variant can not have an array type as an alternative.");
1658 static_assert(detail_variant::all<!std::is_reference<Ts>::value...>::value,
1659 "variant can not have a reference type as an alternative.");
1661 static_assert(detail_variant::all<!std::is_void<Ts>::value...>::value,
1662 "variant can not have a void type as an alternative.");
1666 typename Front = detail_variant::type_pack_element_t<0, Ts...>,
1667 std::enable_if_t<std::is_default_constructible<Front>::value,
int> = 0>
1668 inline constexpr variant() noexcept(
1669 std::is_nothrow_default_constructible<Front>::value)
1670 : impl_(in_place_index_t<0>{}) {}
1672 variant(
const variant &) =
default;
1673 variant(variant &&) =
default;
1677 typename Decayed = std::decay_t<Arg>,
1678 std::enable_if_t<!std::is_same<Decayed, variant>::value,
int> = 0,
1679 std::enable_if_t<!detail_variant::is_in_place_index<Decayed>::value,
int> = 0,
1680 std::enable_if_t<!detail_variant::is_in_place_type<Decayed>::value,
int> = 0,
1681 std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1682 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1683 std::enable_if_t<std::is_constructible<T, Arg>::value,
int> = 0>
1684 inline constexpr variant(Arg &&arg) noexcept(
1685 std::is_nothrow_constructible<T, Arg>::value)
1686 : impl_(in_place_index_t<I>{}, std::forward<Arg>(arg)) {}
1691 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1692 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1693 inline explicit constexpr variant(
1694 in_place_index_t<I>,
1695 Args &&... args) noexcept(std::is_nothrow_constructible<T,
1697 : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1703 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1704 std::enable_if_t<std::is_constructible<T,
1705 std::initializer_list<Up> &,
1708 inline explicit constexpr variant(
1709 in_place_index_t<I>,
1710 std::initializer_list<Up> il,
1711 Args &&... args) noexcept(std::
1712 is_nothrow_constructible<
1714 std::initializer_list<Up> &,
1716 : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1721 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1722 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1723 inline explicit constexpr variant(
1725 Args &&... args) noexcept(std::is_nothrow_constructible<T,
1727 : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1733 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1734 std::enable_if_t<std::is_constructible<T,
1735 std::initializer_list<Up> &,
1738 inline explicit constexpr variant(
1740 std::initializer_list<Up> il,
1741 Args &&... args) noexcept(std::
1742 is_nothrow_constructible<
1744 std::initializer_list<Up> &,
1746 : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1748 ~variant() =
default;
1750 variant &operator=(
const variant &) =
default;
1751 variant &operator=(variant &&) =
default;
1753 template <
typename Arg,
1754 std::enable_if_t<!std::is_same<std::decay_t<Arg>, variant>::value,
1756 std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1757 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1758 std::enable_if_t<(std::is_assignable<T &, Arg>::value &&
1759 std::is_constructible<T, Arg>::value),
1761 inline variant &
operator=(Arg &&arg) noexcept(
1762 (std::is_nothrow_assignable<T &, Arg>::value &&
1763 std::is_nothrow_constructible<T, Arg>::value)) {
1764 impl_.template assign<I>(std::forward<Arg>(arg));
1771 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1772 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1773 inline T &emplace(Args &&... args) {
1774 return impl_.template emplace<I>(std::forward<Args>(args)...);
1781 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1782 std::enable_if_t<std::is_constructible<T,
1783 std::initializer_list<Up> &,
1786 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1787 return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1793 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1794 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1795 inline T &emplace(Args &&... args) {
1796 return impl_.template emplace<I>(std::forward<Args>(args)...);
1803 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1804 std::enable_if_t<std::is_constructible<T,
1805 std::initializer_list<Up> &,
1808 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1809 return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1812 inline constexpr
bool valueless_by_exception() const noexcept {
1813 return impl_.valueless_by_exception();
1816 inline constexpr std::size_t index() const noexcept {
1817 return impl_.index();
1820 template <
bool Dummy =
true,
1822 detail_variant::all<Dummy,
1823 (detail_variant::dependent_type<std::is_move_constructible<Ts>,
1825 detail_variant::dependent_type<detail_variant::is_swappable<Ts>,
1826 Dummy>::value)...>::value,
1828 inline void swap(variant &that) noexcept(
1829 detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1830 detail_variant::is_nothrow_swappable<Ts>::value)...>::value) {
1831 impl_.swap(that.impl_);
1835 detail_variant::impl<Ts...> impl_;
1837 friend struct detail_variant::access::variant;
1838 friend struct detail_variant::visitation::variant;
1841 template <std::size_t I,
typename... Ts>
1842 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
1843 return v.index() == I;
1846 template <
typename T,
typename... Ts>
1847 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
1848 return holds_alternative<detail_variant::find_index_checked<T, Ts...>::value>(v);
1851 namespace detail_variant {
1852 template <std::
size_t I,
typename V>
1853 struct generic_get_impl {
1854 constexpr generic_get_impl(
int) noexcept {}
1856 constexpr
auto&& operator()(V &&v)
const
1858 access::variant::get_alt<I>(std::forward<V>(v)).value)
1861 template <std::
size_t I,
typename V>
1862 inline constexpr
auto&& generic_get(V &&v)
1863 AUTO_REFREF_RETURN(generic_get_impl<I, V>(
1864 holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
1865 std::forward<V>(v)))
1868 template <std::size_t I,
typename... Ts>
1869 inline constexpr variant_alternative_t<I, variant<Ts...>> &
get(
1870 variant<Ts...> &v) {
1871 return detail_variant::generic_get<I>(v);
1874 template <std::size_t I,
typename... Ts>
1875 inline constexpr variant_alternative_t<I, variant<Ts...>> &&
get(
1876 variant<Ts...> &&v) {
1877 return detail_variant::generic_get<I>(std::move(v));
1880 template <std::size_t I,
typename... Ts>
1881 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &
get(
1882 const variant<Ts...> &v) {
1883 return detail_variant::generic_get<I>(v);
1886 template <std::size_t I,
typename... Ts>
1887 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &&
get(
1888 const variant<Ts...> &&v) {
1889 return detail_variant::generic_get<I>(std::move(v));
1892 template <
typename T,
typename... Ts>
1893 inline constexpr T &
get(variant<Ts...> &v) {
1894 return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1897 template <
typename T,
typename... Ts>
1898 inline constexpr T &&
get(variant<Ts...> &&v) {
1899 return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1902 template <
typename T,
typename... Ts>
1903 inline constexpr
const T &
get(
const variant<Ts...> &v) {
1904 return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1907 template <
typename T,
typename... Ts>
1908 inline constexpr
const T &&
get(
const variant<Ts...> &&v) {
1909 return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1912 namespace detail_variant {
1914 template <std::
size_t I,
typename V>
1915 inline constexpr
auto* generic_get_if(V* v) noexcept {
1916 return v && holds_alternative<I>(*v)
1917 ? std::addressof(access::variant::get_alt<I>(*v).value)
1923 template <std::size_t I,
typename... Ts>
1924 inline constexpr std::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
1925 get_if(variant<Ts...> *v) noexcept {
1926 return detail_variant::generic_get_if<I>(v);
1929 template <std::size_t I,
typename... Ts>
1930 inline constexpr std::add_pointer_t<
1931 const variant_alternative_t<I, variant<Ts...>>>
1932 get_if(
const variant<Ts...> *v) noexcept {
1933 return detail_variant::generic_get_if<I>(v);
1936 template <
typename T,
typename... Ts>
1937 inline constexpr std::add_pointer_t<T>
1938 get_if(variant<Ts...> *v) noexcept {
1939 return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1942 template <
typename T,
typename... Ts>
1943 inline constexpr std::add_pointer_t<const T>
1944 get_if(
const variant<Ts...> *v) noexcept {
1945 return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1948 namespace detail_variant {
1949 template <
typename RelOp>
1950 struct convert_to_bool {
1951 template <
typename Lhs,
typename Rhs>
1952 inline constexpr
bool operator()(Lhs &&lhs, Rhs &&rhs)
const {
1953 static_assert(std::is_convertible<invoke_result_t<RelOp, Lhs, Rhs>,
1955 "relational operators must return a type"
1956 " implicitly convertible to bool");
1958 RelOp{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
1963 template <
typename... Ts>
1964 inline constexpr
bool operator==(
const variant<Ts...> &lhs,
1965 const variant<Ts...> &rhs) {
1966 using detail_variant::visitation::variant;
1967 using equal_to = detail_variant::convert_to_bool<std::equal_to<>>;
1968 if (lhs.index() != rhs.index())
return false;
1969 if (lhs.valueless_by_exception())
return true;
1970 return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
1973 template <
typename... Ts>
1974 inline constexpr
bool operator!=(
const variant<Ts...> &lhs,
1975 const variant<Ts...> &rhs) {
1976 using detail_variant::visitation::variant;
1977 using not_equal_to = detail_variant::convert_to_bool<std::not_equal_to<>>;
1978 if (lhs.index() != rhs.index())
return true;
1979 if (lhs.valueless_by_exception())
return false;
1980 return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
1983 template <
typename... Ts>
1984 inline constexpr
bool operator<(
const variant<Ts...> &lhs,
1985 const variant<Ts...> &rhs) {
1986 using detail_variant::visitation::variant;
1987 using less = detail_variant::convert_to_bool<std::less<>>;
1988 if (rhs.valueless_by_exception())
return false;
1989 if (lhs.valueless_by_exception())
return true;
1990 if (lhs.index() < rhs.index())
return true;
1991 if (lhs.index() > rhs.index())
return false;
1992 return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
1995 template <
typename... Ts>
1996 inline constexpr
bool operator>(
const variant<Ts...> &lhs,
1997 const variant<Ts...> &rhs) {
1998 using detail_variant::visitation::variant;
1999 using greater = detail_variant::convert_to_bool<std::greater<>>;
2000 if (lhs.valueless_by_exception())
return false;
2001 if (rhs.valueless_by_exception())
return true;
2002 if (lhs.index() > rhs.index())
return true;
2003 if (lhs.index() < rhs.index())
return false;
2004 return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
2007 template <
typename... Ts>
2008 inline constexpr
bool operator<=(
const variant<Ts...> &lhs,
2009 const variant<Ts...> &rhs) {
2010 using detail_variant::visitation::variant;
2011 using less_equal = detail_variant::convert_to_bool<std::less_equal<>>;
2012 if (lhs.valueless_by_exception())
return true;
2013 if (rhs.valueless_by_exception())
return false;
2014 if (lhs.index() < rhs.index())
return true;
2015 if (lhs.index() > rhs.index())
return false;
2016 return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
2019 template <
typename... Ts>
2020 inline constexpr
bool operator>=(
const variant<Ts...> &lhs,
2021 const variant<Ts...> &rhs) {
2022 using detail_variant::visitation::variant;
2023 using greater_equal = detail_variant::convert_to_bool<std::greater_equal<>>;
2024 if (rhs.valueless_by_exception())
return true;
2025 if (lhs.valueless_by_exception())
return false;
2026 if (lhs.index() > rhs.index())
return true;
2027 if (lhs.index() < rhs.index())
return false;
2028 return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
2031 namespace detail_variant {
2033 inline constexpr
bool any(std::initializer_list<bool> bs) {
2044 template <
typename Visitor,
typename... Vs>
2045 inline constexpr decltype(
auto)
visit(Visitor &&visitor, Vs &&... vs) {
2046 return (!detail_variant::any({vs.valueless_by_exception()...})
2048 : throw_bad_variant_access()),
2049 detail_variant::visitation::variant::visit_value(
2050 std::forward<Visitor>(visitor), std::forward<Vs>(vs)...);
2053 template <
typename... Ts>
2054 inline auto swap(variant<Ts...> &lhs,
2055 variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
2056 -> decltype(lhs.swap(rhs)) {
2060 namespace detail_variant {
2062 template <
typename T,
typename...>
2063 using enabled_type = T;
2067 template <
typename H,
typename K>
2068 constexpr
bool meets_requirements() noexcept {
2069 return std::is_copy_constructible<H>::value &&
2070 std::is_move_constructible<H>::value &&
2071 detail_variant::is_invocable_r<std::size_t, H, const K &>::value;
2074 template <
typename K>
2075 constexpr
bool is_enabled() noexcept {
2076 using H = std::hash<K>;
2077 return meets_requirements<H, K>() &&
2078 std::is_default_constructible<H>::value &&
2079 std::is_copy_assignable<H>::value &&
2080 std::is_move_assignable<H>::value;
2087 #undef AUTO_REFREF_RETURN
2094 template <
typename... Ts>
2095 struct hash<
gul14::detail_variant::enabled_type<
2096 gul14::variant<Ts...>,
2097 std::enable_if_t<gul14::detail_variant::all<gul14::detail_variant::hash::is_enabled<
2098 std::remove_const_t<Ts>>()...>::value>>> {
2100 using result_type = std::size_t;
2102 inline result_type operator()(
const argument_type &v)
const {
2103 using gul14::detail_variant::visitation::variant;
2104 std::size_t result =
2105 v.valueless_by_exception()
2107 : variant::visit_alt(
2108 [](
const auto &alt) {
2109 using alt_type = std::decay_t<decltype(alt)>;
2110 using value_type = std::remove_const_t<
2111 typename alt_type::value_type>;
2112 return hash<value_type>{}(alt.value);
2115 return hash_combine(result, hash<std::size_t>{}(v.index()));
2119 static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
2120 return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
The exception thrown if the wrong type is accessed on a gul14::variant.
Definition: variant.h:49
A "type-safe union".
Definition: variant.h:71
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition: SmallVector.h:1656
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
void void_t
A type mapping an arbitrary list of types to void (for SFINAE).
Definition: traits.h:98
constexpr decltype(auto) visit(Visitor &&visitor_fct, Variants &&... variants)
Call a visitor function with the actual objects stored in the given variants.
auto make_overload_set(Fct... f)
Create an OverloadSet from an arbitrary number of function objects.
Definition: variant.h:138
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
A function object that works like an overload set of functions.
Definition: variant.h:105
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.