20 #ifndef GUL14_VARIANT_H_
21 #define GUL14_VARIANT_H_
26 #include <initializer_list>
29 #include <type_traits>
52 virtual const char* what()
const noexcept
override
54 return "bad_variant_access";
71 template <
typename... Ts>
90 template <
typename Visitor,
typename... Variants>
91 inline constexpr decltype(
auto)
visit(Visitor&& visitor_fct, Variants&&... variants);
104 template <typename Fct1, typename... Fcts>
107 using Fct1::operator();
116 template <
typename Fct1>
119 using Fct1::operator();
138 template <
typename... Fct>
150 #ifndef __has_attribute
151 #define __has_attribute(x) 0
154 #ifndef __has_builtin
155 #define __has_builtin(x) 0
158 #if __has_attribute(always_inline) || defined(__GNUC__)
159 #define GUL14_ALWAYS_INLINE __attribute__((__always_inline__)) inline
160 #elif defined(_MSC_VER)
161 #define GUL14_ALWAYS_INLINE __forceinline
163 #define GUL14_ALWAYS_INLINE inline
166 #if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
167 #define GUL14_BUILTIN_UNREACHABLE __builtin_unreachable()
168 #elif defined(_MSC_VER)
169 #define GUL14_BUILTIN_UNREACHABLE __assume(false)
171 #define GUL14_BUILTIN_UNREACHABLE
175 namespace detail_variant {
177 template <std::
size_t I,
typename T>
178 struct indexed_type : std::integral_constant<std::size_t, I> {
using type = T; };
180 template <
typename T, std::
size_t N>
182 constexpr
const T &operator[](std::size_t index)
const {
return data[index]; }
183 T data[N == 0 ? 1 : N];
186 template <
typename T,
bool>
187 struct dependent_type : T {};
189 template <
typename Is, std::
size_t J>
192 template <
typename Is, std::
size_t J>
193 using push_back_t =
typename push_back<Is, J>::type;
195 template <std::size_t... Is, std::size_t J>
196 struct push_back<std::index_sequence<Is...>, J> {
197 using type = std::index_sequence<Is..., J>;
200 #if __has_builtin(__type_pack_element) && !(defined(__ICC))
201 template <std::size_t I,
typename... Ts>
202 using type_pack_element_t = __type_pack_element<I, Ts...>;
204 template <std::size_t I,
typename... Ts>
205 struct type_pack_element_impl {
210 template <std::size_t... Is>
211 struct set<std::index_sequence<Is...>> : indexed_type<Is, Ts>... {};
213 template <
typename T>
214 inline static std::enable_if<true, T> impl(indexed_type<I, T>);
216 inline static std::enable_if<false> impl(...);
219 using type = decltype(impl(set<std::index_sequence_for<Ts...>>{}));
222 template <std::size_t I,
typename... Ts>
223 using type_pack_element =
typename type_pack_element_impl<I, Ts...>::type;
225 template <std::size_t I,
typename... Ts>
226 using type_pack_element_t =
typename type_pack_element<I, Ts...>::type;
229 template <
bool... Bs>
230 using all = std::is_same<std::integer_sequence<bool,
true, Bs...>,
231 std::integer_sequence<bool, Bs...,
true>>;
234 namespace detail_swappable {
238 template <
typename T>
239 struct is_swappable {
241 template <
typename U,
242 typename = decltype(
swap(std::declval<U &>(),
243 std::declval<U &>()))>
244 inline static std::true_type test(
int);
246 template <
typename U>
247 inline static std::false_type test(...);
250 static constexpr
bool value = decltype(test<T>(0))::value;
253 template <
bool IsSwappable,
typename T>
254 struct is_nothrow_swappable {
255 static constexpr
bool value =
256 noexcept(
swap(std::declval<T &>(), std::declval<T &>()));
259 template <
typename T>
260 struct is_nothrow_swappable<false, T> : std::false_type {};
264 using detail_swappable::is_swappable;
266 template <
typename T>
267 using is_nothrow_swappable =
268 detail_swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
272 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
274 [[noreturn]]
inline void throw_bad_variant_access() {
275 throw bad_variant_access{};
278 template <
typename T>
281 template <
typename T>
282 constexpr std::size_t variant_size_v = variant_size<T>::value;
284 template <
typename T>
285 struct variant_size<const T> : variant_size<T> {};
287 template <
typename T>
288 struct variant_size<volatile T> : variant_size<T> {};
290 template <
typename T>
291 struct variant_size<const volatile T> : variant_size<T> {};
293 template <
typename... Ts>
294 struct variant_size<variant<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {};
296 template <std::
size_t I,
typename T>
297 struct variant_alternative;
299 template <std::
size_t I,
typename T>
300 using variant_alternative_t =
typename variant_alternative<I, T>::type;
302 template <std::
size_t I,
typename T>
303 struct variant_alternative<I, const T>
304 : std::add_const<variant_alternative_t<I, T>> {};
306 template <std::
size_t I,
typename T>
307 struct variant_alternative<I, volatile T>
308 : std::add_volatile<variant_alternative_t<I, T>> {};
310 template <std::
size_t I,
typename T>
311 struct variant_alternative<I, const volatile T>
312 : std::add_cv<variant_alternative_t<I, T>> {};
314 template <std::size_t I,
typename... Ts>
315 struct variant_alternative<I, variant<Ts...>> {
316 static_assert(I <
sizeof...(Ts),
317 "index out of bounds in `std::variant_alternative<>`");
318 using type =
typename detail_variant::type_pack_element_t<I, Ts...>;
321 constexpr std::size_t variant_npos =
static_cast<std::size_t
>(-1);
323 namespace detail_variant {
325 constexpr std::size_t not_found =
static_cast<std::size_t
>(-1);
326 constexpr std::size_t ambiguous =
static_cast<std::size_t
>(-2);
328 template <
typename T,
typename... Ts>
329 inline constexpr std::size_t find_index() {
330 constexpr detail_variant::array<bool,
sizeof...(Ts)> matches = {
331 {std::is_same<T, Ts>::value...}
333 std::size_t result = not_found;
334 for (std::size_t i = 0; i <
sizeof...(Ts); ++i) {
336 if (result != not_found) {
345 template <std::
size_t I>
346 using find_index_sfinae_impl =
347 std::enable_if_t<I != not_found && I != ambiguous,
348 std::integral_constant<std::size_t, I>>;
350 template <
typename T,
typename... Ts>
351 using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
353 template <std::
size_t I>
354 struct find_index_checked_impl : std::integral_constant<std::size_t, I> {
355 static_assert(I != not_found,
"the specified type is not found.");
356 static_assert(I != ambiguous,
"the specified type is ambiguous.");
359 template <
typename T,
typename... Ts>
360 using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
362 struct valueless_t {};
364 enum class Trait { TriviallyAvailable, Available, Unavailable };
366 template <
typename T,
367 template <
typename>
class IsTriviallyAvailable,
368 template <
typename>
class IsAvailable>
369 inline constexpr Trait trait() {
370 return IsTriviallyAvailable<T>::value
371 ? Trait::TriviallyAvailable
372 : IsAvailable<T>::value ? Trait::Available
373 : Trait::Unavailable;
376 template <
typename... Traits>
377 inline constexpr Trait common_trait(Traits... traits_) {
378 Trait result = Trait::TriviallyAvailable;
379 detail_variant::array<Trait,
sizeof...(Traits)> traits = {{traits_...}};
380 for (std::size_t i = 0; i <
sizeof...(Traits); ++i) {
382 if (
static_cast<int>(t) >
static_cast<int>(result)) {
389 template <
typename... Ts>
391 static constexpr Trait copy_constructible_trait =
392 common_trait(trait<Ts,
393 std::is_trivially_copy_constructible,
394 std::is_copy_constructible>()...);
396 static constexpr Trait move_constructible_trait =
397 common_trait(trait<Ts,
398 std::is_trivially_move_constructible,
399 std::is_move_constructible>()...);
401 static constexpr Trait copy_assignable_trait =
402 common_trait(copy_constructible_trait,
404 std::is_trivially_copy_assignable,
405 std::is_copy_assignable>()...);
407 static constexpr Trait move_assignable_trait =
408 common_trait(move_constructible_trait,
410 std::is_trivially_move_assignable,
411 std::is_move_assignable>()...);
413 static constexpr Trait destructible_trait =
414 common_trait(trait<Ts,
415 std::is_trivially_destructible,
416 std::is_destructible>()...);
421 struct recursive_union {
422 template <
typename V>
423 inline static constexpr
auto &&get_alt(V &&v, in_place_index_t<0>) {
424 return std::forward<V>(v).head_;
427 template <
typename V, std::
size_t I>
428 inline static constexpr
auto &&get_alt(V &&v, in_place_index_t<I>) {
429 return get_alt(std::forward<V>(v).tail_, in_place_index_t<I - 1>{});
434 template <std::
size_t I,
typename V>
435 inline static constexpr
auto&& get_alt(V &&v)
437 AUTO_REFREF_RETURN(recursive_union::get_alt(
438 std::forward<V>(v).data_, in_place_index_t<I>{}))
440 AUTO_REFREF_RETURN(recursive_union::get_alt(
441 data(std::forward<V>(v)), in_place_index_t<I>{}))
446 template <std::
size_t I,
typename V>
447 inline static constexpr
auto&& get_alt(V &&v)
448 AUTO_REFREF_RETURN(base::get_alt<I>(std::forward<V>(v).impl_))
453 namespace visitation {
455 #if !defined(_MSC_VER)
456 #define GUL14_VARIANT_SWITCH_VISIT
460 template <
typename Visitor,
typename... Vs>
461 using dispatch_result_t = decltype(
462 invoke(std::declval<Visitor>(),
463 access::base::get_alt<0>(std::declval<Vs>())...));
465 template <
typename Expected>
467 template <
typename Actual>
468 inline static constexpr
bool but_got() {
469 return std::is_same<Expected, Actual>::value;
473 template <
typename Expected,
typename Actual>
474 struct visit_return_type_check {
476 expected<Expected>::template but_got<Actual>(),
477 "`visit` requires the visitor to have a single return type");
479 template <
typename Visitor,
typename... Alts>
480 inline static constexpr decltype(
auto)
481 invoke(Visitor &&visitor, Alts &&... alts)
484 std::forward<Visitor>(visitor), std::forward<Alts>(alts)...);
488 #ifdef GUL14_VARIANT_SWITCH_VISIT
489 template <
bool B,
typename R,
typename... ITs>
492 template <
typename R,
typename... ITs>
493 struct dispatcher<false, R, ITs...> {
494 template <std::size_t B,
typename F,
typename... Vs>
495 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
496 F &&,
typename ITs::type &&..., Vs &&...) {
497 GUL14_BUILTIN_UNREACHABLE;
500 template <std::size_t I,
typename F,
typename... Vs>
501 GUL14_ALWAYS_INLINE
static constexpr R dispatch_case(F &&, Vs &&...) {
502 GUL14_BUILTIN_UNREACHABLE;
505 template <std::size_t B,
typename F,
typename... Vs>
506 GUL14_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t,
509 GUL14_BUILTIN_UNREACHABLE;
513 template <
typename R,
typename... ITs>
514 struct dispatcher<true, R, ITs...> {
515 template <std::
size_t B,
typename F>
516 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
517 F &&f,
typename ITs::type &&... visited_vs) {
519 using Actual = decltype(
invoke(
521 access::base::get_alt<ITs::value>(
522 std::forward<typename ITs::type>(visited_vs))...));
525 access::base::get_alt<ITs::value>(
526 std::forward<typename ITs::type>(visited_vs))...);
529 template <std::size_t B,
typename F,
typename V,
typename... Vs>
530 GUL14_ALWAYS_INLINE
static constexpr R dispatch(
531 F &&f,
typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
532 #define GUL14_DISPATCH(I) \
533 dispatcher<(I < std::decay_t<V>::size()), \
536 detail_variant::indexed_type<I, V>>:: \
537 template dispatch<0>(std::forward<F>(f), \
538 std::forward<typename ITs::type>(visited_vs)..., \
539 std::forward<V>(v), \
540 std::forward<Vs>(vs)...)
542 #define GUL14_DEFAULT(I) \
543 dispatcher<(I < std::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
544 std::forward<F>(f), \
545 std::forward<typename ITs::type>(visited_vs)..., \
546 std::forward<V>(v), \
547 std::forward<Vs>(vs)...)
550 case B + 0:
return GUL14_DISPATCH(B + 0);
551 case B + 1:
return GUL14_DISPATCH(B + 1);
552 case B + 2:
return GUL14_DISPATCH(B + 2);
553 case B + 3:
return GUL14_DISPATCH(B + 3);
554 case B + 4:
return GUL14_DISPATCH(B + 4);
555 case B + 5:
return GUL14_DISPATCH(B + 5);
556 case B + 6:
return GUL14_DISPATCH(B + 6);
557 case B + 7:
return GUL14_DISPATCH(B + 7);
558 case B + 8:
return GUL14_DISPATCH(B + 8);
559 case B + 9:
return GUL14_DISPATCH(B + 9);
560 case B + 10:
return GUL14_DISPATCH(B + 10);
561 case B + 11:
return GUL14_DISPATCH(B + 11);
562 case B + 12:
return GUL14_DISPATCH(B + 12);
563 case B + 13:
return GUL14_DISPATCH(B + 13);
564 case B + 14:
return GUL14_DISPATCH(B + 14);
565 case B + 15:
return GUL14_DISPATCH(B + 15);
566 case B + 16:
return GUL14_DISPATCH(B + 16);
567 case B + 17:
return GUL14_DISPATCH(B + 17);
568 case B + 18:
return GUL14_DISPATCH(B + 18);
569 case B + 19:
return GUL14_DISPATCH(B + 19);
570 case B + 20:
return GUL14_DISPATCH(B + 20);
571 case B + 21:
return GUL14_DISPATCH(B + 21);
572 case B + 22:
return GUL14_DISPATCH(B + 22);
573 case B + 23:
return GUL14_DISPATCH(B + 23);
574 case B + 24:
return GUL14_DISPATCH(B + 24);
575 case B + 25:
return GUL14_DISPATCH(B + 25);
576 case B + 26:
return GUL14_DISPATCH(B + 26);
577 case B + 27:
return GUL14_DISPATCH(B + 27);
578 case B + 28:
return GUL14_DISPATCH(B + 28);
579 case B + 29:
return GUL14_DISPATCH(B + 29);
580 case B + 30:
return GUL14_DISPATCH(B + 30);
581 case B + 31:
return GUL14_DISPATCH(B + 31);
582 default:
return GUL14_DEFAULT(B + 32);
586 #undef GUL14_DISPATCH
589 template <std::size_t I,
typename F,
typename... Vs>
590 GUL14_ALWAYS_INLINE
static constexpr R dispatch_case(F &&f,
593 using Actual = decltype(
594 invoke(std::forward<F>(f),
595 access::base::get_alt<I>(std::forward<Vs>(vs))...));
598 access::base::get_alt<I>(std::forward<Vs>(vs))...);
601 template <std::size_t B,
typename F,
typename V,
typename... Vs>
602 GUL14_ALWAYS_INLINE
static constexpr R dispatch_at(std::size_t index,
606 static_assert(detail_variant::all<(std::decay_t<V>::size() ==
607 std::decay_t<Vs>::size())...>::value,
608 "all of the variants must be the same size.");
609 #define GUL14_DISPATCH_AT(I) \
610 dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_case<I>( \
611 std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
613 #define GUL14_DEFAULT(I) \
614 dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_at<I>( \
615 index, std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
618 case B + 0:
return GUL14_DISPATCH_AT(B + 0);
619 case B + 1:
return GUL14_DISPATCH_AT(B + 1);
620 case B + 2:
return GUL14_DISPATCH_AT(B + 2);
621 case B + 3:
return GUL14_DISPATCH_AT(B + 3);
622 case B + 4:
return GUL14_DISPATCH_AT(B + 4);
623 case B + 5:
return GUL14_DISPATCH_AT(B + 5);
624 case B + 6:
return GUL14_DISPATCH_AT(B + 6);
625 case B + 7:
return GUL14_DISPATCH_AT(B + 7);
626 case B + 8:
return GUL14_DISPATCH_AT(B + 8);
627 case B + 9:
return GUL14_DISPATCH_AT(B + 9);
628 case B + 10:
return GUL14_DISPATCH_AT(B + 10);
629 case B + 11:
return GUL14_DISPATCH_AT(B + 11);
630 case B + 12:
return GUL14_DISPATCH_AT(B + 12);
631 case B + 13:
return GUL14_DISPATCH_AT(B + 13);
632 case B + 14:
return GUL14_DISPATCH_AT(B + 14);
633 case B + 15:
return GUL14_DISPATCH_AT(B + 15);
634 case B + 16:
return GUL14_DISPATCH_AT(B + 16);
635 case B + 17:
return GUL14_DISPATCH_AT(B + 17);
636 case B + 18:
return GUL14_DISPATCH_AT(B + 18);
637 case B + 19:
return GUL14_DISPATCH_AT(B + 19);
638 case B + 20:
return GUL14_DISPATCH_AT(B + 20);
639 case B + 21:
return GUL14_DISPATCH_AT(B + 21);
640 case B + 22:
return GUL14_DISPATCH_AT(B + 22);
641 case B + 23:
return GUL14_DISPATCH_AT(B + 23);
642 case B + 24:
return GUL14_DISPATCH_AT(B + 24);
643 case B + 25:
return GUL14_DISPATCH_AT(B + 25);
644 case B + 26:
return GUL14_DISPATCH_AT(B + 26);
645 case B + 27:
return GUL14_DISPATCH_AT(B + 27);
646 case B + 28:
return GUL14_DISPATCH_AT(B + 28);
647 case B + 29:
return GUL14_DISPATCH_AT(B + 29);
648 case B + 30:
return GUL14_DISPATCH_AT(B + 30);
649 case B + 31:
return GUL14_DISPATCH_AT(B + 31);
650 default:
return GUL14_DEFAULT(B + 32);
654 #undef GUL14_DISPATCH_AT
658 template <
typename T>
659 inline static constexpr
const T &at(
const T &elem) noexcept {
663 template <
typename T, std::size_t N,
typename... Is>
664 inline static constexpr
const std::remove_all_extents_t<T> &at(
665 const detail_variant::array<T, N> &elems, std::size_t i, Is... is) noexcept {
666 return at(elems[i], is...);
669 template <
typename F,
typename... Fs>
670 inline static constexpr detail_variant::array<std::decay_t<F>,
sizeof...(Fs) + 1>
671 make_farray(F &&f, Fs &&... fs) {
672 return {{std::forward<F>(f), std::forward<Fs>(fs)...}};
675 template <
typename F,
typename... Vs>
676 struct make_fmatrix_impl {
678 template <std::size_t... Is>
679 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
680 F &&f, Vs &&... vs) {
681 using Expected = dispatch_result_t<F, Vs...>;
682 using Actual = decltype(
invoke(
684 access::base::get_alt<Is>(std::forward<Vs>(vs))...));
687 access::base::get_alt<Is>(std::forward<Vs>(vs))...);
690 template <std::size_t... Is>
691 inline static constexpr
auto impl(std::index_sequence<Is...>) {
692 return &dispatch<Is...>;
695 template <
typename Is, std::size_t... Js,
typename... Ls>
696 inline static constexpr
auto impl(Is,
697 std::index_sequence<Js...>,
699 return make_farray(impl(detail_variant::push_back_t<Is, Js>{}, ls...)...);
703 template <
typename F,
typename... Vs>
704 inline static constexpr
auto make_fmatrix() {
705 return make_fmatrix_impl<F, Vs...>::impl(
706 std::index_sequence<>{},
707 std::make_index_sequence<std::decay_t<Vs>::size()>{}...);
710 template <
typename F,
typename... Vs>
711 struct make_fdiagonal_impl {
712 template <std::
size_t I>
713 inline static constexpr dispatch_result_t<F, Vs...> dispatch(
714 F &&f, Vs &&... vs) {
715 using Expected = dispatch_result_t<F, Vs...>;
716 using Actual = decltype(
717 invoke(std::forward<F>(f),
718 access::base::get_alt<I>(std::forward<Vs>(vs))...));
721 access::base::get_alt<I>(std::forward<Vs>(vs))...);
724 template <std::size_t... Is>
725 inline static constexpr
auto impl(std::index_sequence<Is...>) {
726 return make_farray(&dispatch<Is>...);
730 template <
typename F,
typename V,
typename... Vs>
731 inline static constexpr
auto make_fdiagonal()
732 -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(
733 std::make_index_sequence<std::decay_t<V>::size()>{})) {
734 static_assert(detail_variant::all<(std::decay_t<V>::size() ==
735 std::decay_t<Vs>::size())...>::value,
736 "all of the variants must be the same size.");
737 return make_fdiagonal_impl<F, V, Vs...>::impl(
738 std::make_index_sequence<std::decay_t<V>::size()>{});
743 #if !defined(GUL14_VARIANT_SWITCH_VISIT) && \
744 (!defined(_MSC_VER) || _MSC_VER >= 1910)
745 template <
typename F,
typename... Vs>
746 using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
748 template <
typename F,
typename... Vs>
750 static constexpr fmatrix_t<F, Vs...> value =
751 base::make_fmatrix<F, Vs...>();
754 template <
typename F,
typename... Vs>
755 constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;
757 template <
typename F,
typename... Vs>
758 using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
760 template <
typename F,
typename... Vs>
762 static constexpr fdiagonal_t<F, Vs...> value =
763 base::make_fdiagonal<F, Vs...>();
766 template <
typename F,
typename... Vs>
767 constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;
771 template <
typename Visitor,
typename... Vs>
772 inline static constexpr decltype(
auto) visit_alt(Visitor &&visitor,
774 #ifdef GUL14_VARIANT_SWITCH_VISIT
776 return base::dispatcher<
778 base::dispatch_result_t<Visitor,
780 std::forward<Vs>(vs)))...>>::
781 template dispatch<0>(std::forward<Visitor>(visitor),
782 as_base(std::forward<Vs>(vs))...);
784 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
788 decltype(as_base(std::forward<Vs>(vs)))...>::value,
789 vs.index()...)(std::forward<Visitor>(visitor),
790 as_base(std::forward<Vs>(vs))...);
795 base::make_fmatrix<Visitor &&,
796 decltype(as_base(std::forward<Vs>(vs)))...>(),
797 vs.index()...)(std::forward<Visitor>(visitor),
798 as_base(std::forward<Vs>(vs))...);
802 template <
typename Visitor,
typename... Vs>
803 inline static constexpr decltype(
auto) visit_alt_at(std::
size_t index,
806 #ifdef GUL14_VARIANT_SWITCH_VISIT
808 return base::dispatcher<
810 base::dispatch_result_t<Visitor,
812 std::forward<Vs>(vs)))...>>::
813 template dispatch_at<0>(index,
814 std::forward<Visitor>(visitor),
815 as_base(std::forward<Vs>(vs))...);
817 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
820 fdiagonal<Visitor &&,
821 decltype(as_base(std::forward<Vs>(vs)))...>::value,
822 index)(std::forward<Visitor>(visitor),
823 as_base(std::forward<Vs>(vs))...);
828 base::make_fdiagonal<Visitor &&,
829 decltype(as_base(std::forward<Vs>(vs)))...>(),
830 index)(std::forward<Visitor>(visitor),
831 as_base(std::forward<Vs>(vs))...);
838 template <
typename Visitor>
840 template <
typename... Values>
841 inline static constexpr
bool does_not_handle() {
846 template <
typename Visitor,
typename... Values>
847 struct visit_exhaustiveness_check {
848 static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
849 "`visit` requires the visitor to be exhaustive.");
851 inline static constexpr decltype(
auto)
852 invoke(Visitor &&visitor, Values &&... values)
855 std::forward<Values>(values)...);
859 template <
typename Visitor>
860 struct value_visitor {
863 template <
typename... Alts>
864 inline constexpr decltype(
auto) operator()(Alts &&... alts)
const
866 return visit_exhaustiveness_check<
868 decltype((std::forward<Alts>(alts).value))...>
::
869 invoke(std::forward<Visitor>(visitor_),
870 std::forward<Alts>(alts).value...);
874 template <
typename Visitor>
875 inline static constexpr
auto make_value_visitor(Visitor &&visitor) {
876 return value_visitor<Visitor>{std::forward<Visitor>(visitor)};
880 template <
typename Visitor,
typename... Vs>
881 inline static constexpr decltype(
auto) visit_alt(Visitor &&visitor, Vs &&... vs)
883 return alt::visit_alt(std::forward<Visitor>(visitor),
884 std::forward<Vs>(vs).impl_...);
887 template <
typename Visitor,
typename... Vs>
888 inline static constexpr decltype(
auto) visit_alt_at(std::
size_t index,
892 return alt::visit_alt_at(index, std::forward<Visitor>(visitor),
893 std::forward<Vs>(vs).impl_...);
896 template <
typename Visitor,
typename... Vs>
897 inline static constexpr decltype(
auto) visit_value(Visitor &&visitor,
900 return visit_alt(make_value_visitor(std::forward<Visitor>(visitor)),
901 std::forward<Vs>(vs)...);
904 template <
typename Visitor,
typename... Vs>
905 inline static constexpr decltype(
auto) visit_value_at(std::
size_t index,
909 return visit_alt_at(index, make_value_visitor(std::forward<Visitor>(visitor)),
910 std::forward<Vs>(vs)...);
916 template <std::
size_t Index,
typename T>
918 using value_type = T;
921 #pragma warning(push)
922 #pragma warning(disable : 4244)
924 template <
typename... Args>
925 inline explicit constexpr alt(in_place_t, Args &&... args)
926 : value(std::forward<Args>(args)...) {}
934 template <Trait DestructibleTrait, std::size_t Index,
typename... Ts>
935 union recursive_union;
937 template <Trait DestructibleTrait, std::
size_t Index>
938 union recursive_union<DestructibleTrait, Index> {};
940 #define GUL14_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
941 template <std::size_t Index, typename T, typename... Ts> \
942 union recursive_union<destructible_trait, Index, T, Ts...> { \
944 inline explicit constexpr recursive_union(valueless_t) noexcept \
947 template <typename... Args> \
948 inline explicit constexpr recursive_union(in_place_index_t<0>, \
950 : head_(in_place_t{}, std::forward<Args>(args)...) {} \
952 template <std::size_t I, typename... Args> \
953 inline explicit constexpr recursive_union(in_place_index_t<I>, \
955 : tail_(in_place_index_t<I - 1>{}, std::forward<Args>(args)...) {} \
957 recursive_union(const recursive_union &) = default; \
958 recursive_union(recursive_union &&) = default; \
962 recursive_union &operator=(const recursive_union &) = default; \
963 recursive_union &operator=(recursive_union &&) = default; \
967 alt<Index, T> head_; \
968 recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
970 friend struct access::recursive_union; \
973 GUL14_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
974 ~recursive_union() =
default;);
975 GUL14_VARIANT_RECURSIVE_UNION(Trait::Available,
976 ~recursive_union() {});
977 GUL14_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
978 ~recursive_union() =
delete;);
980 #undef GUL14_VARIANT_RECURSIVE_UNION
982 template <
typename... Ts>
983 using index_t =
typename std::conditional<
984 sizeof...(Ts) < (std::numeric_limits<unsigned char>::max)(),
986 typename std::conditional<
987 sizeof...(Ts) < (std::numeric_limits<unsigned short>::max)(),
992 template <Trait DestructibleTrait,
typename... Ts>
995 inline explicit constexpr base(valueless_t tag) noexcept
996 : data_(tag), index_(
static_cast<index_t<Ts...
>>(-1)) {}
998 template <std::size_t I,
typename... Args>
999 inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
1000 : data_(in_place_index_t<I>{}, std::forward<Args>(args)...),
1003 inline constexpr
bool valueless_by_exception() const noexcept {
1004 return index_ ==
static_cast<index_t<Ts...
>>(-1);
1007 inline constexpr std::size_t index() const noexcept {
1008 return valueless_by_exception() ? variant_npos : index_;
1012 using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
1014 friend inline constexpr base &as_base(base &b) {
return b; }
1015 friend inline constexpr
const base &as_base(
const base &b) {
return b; }
1016 friend inline constexpr base &&as_base(base &&b) {
return std::move(b); }
1017 friend inline constexpr
const base &&as_base(
const base &&b) {
return std::move(b); }
1019 friend inline constexpr data_t &data(base &b) {
return b.data_; }
1020 friend inline constexpr
const data_t &data(
const base &b) {
return b.data_; }
1021 friend inline constexpr data_t &&data(base &&b) {
return std::move(b).data_; }
1022 friend inline constexpr
const data_t &&data(
const base &&b) {
return std::move(b).data_; }
1024 inline static constexpr std::size_t size() {
return sizeof...(Ts); }
1027 index_t<Ts...> index_;
1029 friend struct access::base;
1030 friend struct visitation::base;
1035 #pragma warning(push)
1036 #pragma warning(disable : 4100)
1038 template <
typename Alt>
1039 inline void operator()(Alt &alt)
const noexcept { alt.~Alt(); }
1041 #pragma warning(pop)
1045 #if !defined(_MSC_VER) || _MSC_VER >= 1910
1046 #define GUL14_INHERITING_CTOR(type, base) using base::base;
1048 #define GUL14_INHERITING_CTOR(type, base) \
1049 template <typename... Args> \
1050 inline explicit constexpr type(Args &&... args) \
1051 : base(std::forward<Args>(args)...) {}
1054 template <
typename Traits, Trait = Traits::destructible_trait>
1057 #define GUL14_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
1058 template <typename... Ts> \
1059 class destructor<traits<Ts...>, destructible_trait> \
1060 : public base<destructible_trait, Ts...> { \
1061 using super = base<destructible_trait, Ts...>; \
1064 GUL14_INHERITING_CTOR(destructor, super) \
1065 using super::operator=; \
1067 destructor(const destructor &) = default; \
1068 destructor(destructor &&) = default; \
1070 destructor &operator=(const destructor &) = default; \
1071 destructor &operator=(destructor &&) = default; \
1077 GUL14_VARIANT_DESTRUCTOR(
1078 Trait::TriviallyAvailable,
1079 ~destructor() =
default;,
1080 inline void destroy() noexcept {
1081 this->index_ =
static_cast<index_t<Ts...
>>(-1);
1084 GUL14_VARIANT_DESTRUCTOR(
1086 ~destructor() { destroy(); },
1087 inline void destroy() noexcept {
1088 if (!this->valueless_by_exception()) {
1089 visitation::alt::visit_alt(dtor{}, *
this);
1091 this->index_ =
static_cast<index_t<Ts...
>>(-1);
1094 GUL14_VARIANT_DESTRUCTOR(
1096 ~destructor() =
delete;,
1097 inline void destroy() noexcept = delete;);
1099 #undef GUL14_VARIANT_DESTRUCTOR
1101 template <
typename Traits>
1102 class constructor :
public destructor<Traits> {
1103 using super = destructor<Traits>;
1106 GUL14_INHERITING_CTOR(constructor, super)
1107 using super::operator=;
1110 template <std::size_t I,
typename T,
typename... Args>
1111 inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
1112 auto *result = ::new (
static_cast<void *
>(std::addressof(a)))
1113 alt<I, T>(in_place_t{}, std::forward<Args>(args)...);
1114 return result->value;
1117 template <
typename Rhs>
1118 inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
1120 if (!rhs.valueless_by_exception()) {
1121 visitation::alt::visit_alt_at(
1123 [](
auto &lhs_alt,
auto &&rhs_alt) {
1124 constructor::construct_alt(
1125 lhs_alt, std::forward<decltype(rhs_alt)>(rhs_alt).value);
1129 std::forward<Rhs>(rhs));
1130 lhs.index_ = rhs.index_;
1135 template <
typename Traits, Trait = Traits::move_constructible_trait>
1136 class move_constructor;
1138 #define GUL14_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
1139 template <typename... Ts> \
1140 class move_constructor<traits<Ts...>, move_constructible_trait> \
1141 : public constructor<traits<Ts...>> { \
1142 using super = constructor<traits<Ts...>>; \
1145 GUL14_INHERITING_CTOR(move_constructor, super) \
1146 using super::operator=; \
1148 move_constructor(const move_constructor &) = default; \
1150 ~move_constructor() = default; \
1151 move_constructor &operator=(const move_constructor &) = default; \
1152 move_constructor &operator=(move_constructor &&) = default; \
1155 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1156 Trait::TriviallyAvailable,
1157 move_constructor(move_constructor &&that) =
default;);
1159 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1161 move_constructor(move_constructor &&that) noexcept(
1162 detail_variant::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
1163 : move_constructor(valueless_t{}) {
1164 this->generic_construct(*
this, std::move(that));
1167 GUL14_VARIANT_MOVE_CONSTRUCTOR(
1169 move_constructor(move_constructor &&) =
delete;);
1171 #undef GUL14_VARIANT_MOVE_CONSTRUCTOR
1173 template <
typename Traits, Trait = Traits::copy_constructible_trait>
1174 class copy_constructor;
1176 #define GUL14_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
1177 template <typename... Ts> \
1178 class copy_constructor<traits<Ts...>, copy_constructible_trait> \
1179 : public move_constructor<traits<Ts...>> { \
1180 using super = move_constructor<traits<Ts...>>; \
1183 GUL14_INHERITING_CTOR(copy_constructor, super) \
1184 using super::operator=; \
1187 copy_constructor(copy_constructor &&) = default; \
1188 ~copy_constructor() = default; \
1189 copy_constructor &operator=(const copy_constructor &) = default; \
1190 copy_constructor &operator=(copy_constructor &&) = default; \
1193 GUL14_VARIANT_COPY_CONSTRUCTOR(
1194 Trait::TriviallyAvailable,
1195 copy_constructor(
const copy_constructor &that) =
default;);
1197 GUL14_VARIANT_COPY_CONSTRUCTOR(
1199 copy_constructor(
const copy_constructor &that)
1200 : copy_constructor(valueless_t{}) {
1201 this->generic_construct(*
this, that);
1204 GUL14_VARIANT_COPY_CONSTRUCTOR(
1206 copy_constructor(
const copy_constructor &) =
delete;);
1208 #undef GUL14_VARIANT_COPY_CONSTRUCTOR
1210 template <
typename Traits>
1211 class assignment :
public copy_constructor<Traits> {
1212 using super = copy_constructor<Traits>;
1215 GUL14_INHERITING_CTOR(assignment, super)
1216 using super::operator=;
1218 template <std::size_t I,
typename... Args>
1219 inline auto emplace(Args &&... args)
1220 -> decltype(this->construct_alt(access::base::get_alt<I>(*
this),
1221 std::forward<Args>(args)...)) {
1223 auto &result = this->construct_alt(access::base::get_alt<I>(*
this),
1224 std::forward<Args>(args)...);
1230 template <std::
size_t I,
typename T,
typename Arg>
1231 inline void assign_alt(alt<I, T> &a, Arg &&arg) {
1232 if (this->index() == I) {
1234 #pragma warning(push)
1235 #pragma warning(disable : 4244)
1237 a.value = std::forward<Arg>(arg);
1239 #pragma warning(pop)
1243 void operator()(std::true_type)
const {
1244 this_->emplace<I>(std::forward<Arg>(arg_));
1246 void operator()(std::false_type)
const {
1247 this_->emplace<I>(T(std::forward<Arg>(arg_)));
1251 } impl{
this, std::forward<Arg>(arg)};
1252 impl(std::integral_constant<
bool,
1253 std::is_nothrow_constructible<T, Arg>::value ||
1254 !std::is_nothrow_move_constructible<T>::value>{});
1258 template <
typename That>
1259 inline void generic_assign(That &&that) {
1260 if (this->valueless_by_exception() && that.valueless_by_exception()) {
1262 }
else if (that.valueless_by_exception()) {
1265 visitation::alt::visit_alt_at(
1267 [
this](
auto &this_alt,
auto &&that_alt) {
1269 this_alt, std::forward<decltype(that_alt)>(that_alt).value);
1272 std::forward<That>(that));
1277 template <
typename Traits, Trait = Traits::move_assignable_trait>
1278 class move_assignment;
1280 #define GUL14_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
1281 template <typename... Ts> \
1282 class move_assignment<traits<Ts...>, move_assignable_trait> \
1283 : public assignment<traits<Ts...>> { \
1284 using super = assignment<traits<Ts...>>; \
1287 GUL14_INHERITING_CTOR(move_assignment, super) \
1288 using super::operator=; \
1290 move_assignment(const move_assignment &) = default; \
1291 move_assignment(move_assignment &&) = default; \
1292 ~move_assignment() = default; \
1293 move_assignment &operator=(const move_assignment &) = default; \
1297 GUL14_VARIANT_MOVE_ASSIGNMENT(
1298 Trait::TriviallyAvailable,
1299 move_assignment &
operator=(move_assignment &&that) =
default;);
1301 GUL14_VARIANT_MOVE_ASSIGNMENT(
1304 operator=(move_assignment &&that) noexcept(
1305 detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1306 std::is_nothrow_move_assignable<Ts>::value)...>::value) {
1307 this->generic_assign(std::move(that));
1311 GUL14_VARIANT_MOVE_ASSIGNMENT(
1313 move_assignment &
operator=(move_assignment &&) =
delete;);
1315 #undef GUL14_VARIANT_MOVE_ASSIGNMENT
1317 template <
typename Traits, Trait = Traits::copy_assignable_trait>
1318 class copy_assignment;
1320 #define GUL14_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
1321 template <typename... Ts> \
1322 class copy_assignment<traits<Ts...>, copy_assignable_trait> \
1323 : public move_assignment<traits<Ts...>> { \
1324 using super = move_assignment<traits<Ts...>>; \
1327 GUL14_INHERITING_CTOR(copy_assignment, super) \
1328 using super::operator=; \
1330 copy_assignment(const copy_assignment &) = default; \
1331 copy_assignment(copy_assignment &&) = default; \
1332 ~copy_assignment() = default; \
1334 copy_assignment &operator=(copy_assignment &&) = default; \
1337 GUL14_VARIANT_COPY_ASSIGNMENT(
1338 Trait::TriviallyAvailable,
1339 copy_assignment &
operator=(
const copy_assignment &that) =
default;);
1341 GUL14_VARIANT_COPY_ASSIGNMENT(
1343 copy_assignment &
operator=(
const copy_assignment &that) {
1344 this->generic_assign(that);
1348 GUL14_VARIANT_COPY_ASSIGNMENT(
1350 copy_assignment &
operator=(
const copy_assignment &) =
delete;);
1352 #undef GUL14_VARIANT_COPY_ASSIGNMENT
1354 template <
typename... Ts>
1355 class impl :
public copy_assignment<traits<Ts...>> {
1356 using super = copy_assignment<traits<Ts...>>;
1359 GUL14_INHERITING_CTOR(impl, super)
1360 using super::operator=;
1362 impl(
const impl&) =
default;
1363 impl(impl&&) =
default;
1365 impl &operator=(
const impl &) =
default;
1366 impl &operator=(impl &&) =
default;
1368 template <std::
size_t I,
typename Arg>
1369 inline void assign(Arg &&arg) {
1370 this->assign_alt(access::base::get_alt<I>(*
this),
1371 std::forward<Arg>(arg));
1374 inline void swap(impl &that) {
1375 if (this->valueless_by_exception() && that.valueless_by_exception()) {
1377 }
else if (this->index() == that.index()) {
1378 visitation::alt::visit_alt_at(this->index(),
1379 [](
auto &this_alt,
auto &that_alt) {
1381 swap(this_alt.value,
1388 impl *rhs = std::addressof(that);
1389 if (lhs->move_nothrow() && !rhs->move_nothrow()) {
1392 impl tmp(std::move(*rhs));
1397 this->generic_construct(*rhs, std::move(*lhs));
1399 if (tmp.move_nothrow()) {
1400 this->generic_construct(*rhs, std::move(tmp));
1404 this->generic_construct(*lhs, std::move(tmp));
1409 inline constexpr
bool move_nothrow()
const {
1410 return this->valueless_by_exception() ||
1411 detail_variant::array<bool,
sizeof...(Ts)>{
1412 {std::is_nothrow_move_constructible<Ts>::value...}
1417 #undef GUL14_INHERITING_CTOR
1419 template <
typename From,
typename To>
1420 struct is_non_narrowing_convertible {
1421 template <
typename T>
1422 static std::true_type test(T(&&)[1]);
1424 template <
typename T>
1425 static auto impl(
int) -> decltype(test<T>({std::declval<From>()}));
1428 static auto impl(...) -> std::false_type;
1430 static constexpr
bool value = decltype(impl<To>(0))::value;
1433 template <
typename Arg,
1436 bool = std::is_arithmetic<T>::value,
1438 struct overload_leaf {};
1440 template <
typename Arg, std::
size_t I,
typename T>
1441 struct overload_leaf<Arg, I, T, false> {
1442 using impl = std::integral_constant<std::size_t, I> (*)(T);
1443 operator impl()
const {
return nullptr; };
1446 template <
typename Arg, std::
size_t I,
typename T>
1447 struct overload_leaf<
1452 #if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
1455 std::is_same<remove_cvref_t<T>,
bool>::value
1456 ? std::is_same<remove_cvref_t<Arg>,
bool>::value
1457 : is_non_narrowing_convertible<Arg, T>::value>
1460 using impl = std::integral_constant<std::size_t, I> (*)(T);
1461 operator impl()
const {
return nullptr; };
1464 template <
typename Arg,
typename... Ts>
1465 struct overload_impl {
1470 template <std::size_t... Is>
1471 struct impl<std::index_sequence<Is...>> : overload_leaf<Arg, Is, Ts>... {};
1474 using type = impl<std::index_sequence_for<Ts...>>;
1477 template <
typename Arg,
typename... Ts>
1478 using overload =
typename overload_impl<Arg, Ts...>::type;
1480 template <
typename Arg,
typename... Ts>
1483 template <
typename T>
1484 struct is_in_place_index : std::false_type {};
1486 template <std::
size_t I>
1487 struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
1489 template <
typename T>
1490 struct is_in_place_type : std::false_type {};
1492 template <
typename T>
1493 struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
1497 template <
typename... Ts>
1499 static_assert(0 <
sizeof...(Ts),
1500 "variant must consist of at least one alternative.");
1502 static_assert(detail_variant::all<!std::is_array<Ts>::value...>::value,
1503 "variant can not have an array type as an alternative.");
1505 static_assert(detail_variant::all<!std::is_reference<Ts>::value...>::value,
1506 "variant can not have a reference type as an alternative.");
1508 static_assert(detail_variant::all<!std::is_void<Ts>::value...>::value,
1509 "variant can not have a void type as an alternative.");
1513 typename Front = detail_variant::type_pack_element_t<0, Ts...>,
1514 std::enable_if_t<std::is_default_constructible<Front>::value,
int> = 0>
1515 inline constexpr variant() noexcept(
1516 std::is_nothrow_default_constructible<Front>::value)
1517 : impl_(in_place_index_t<0>{}) {}
1519 variant(
const variant &) =
default;
1520 variant(variant &&) =
default;
1524 typename Decayed = std::decay_t<Arg>,
1525 std::enable_if_t<!std::is_same<Decayed, variant>::value,
int> = 0,
1526 std::enable_if_t<!detail_variant::is_in_place_index<Decayed>::value,
int> = 0,
1527 std::enable_if_t<!detail_variant::is_in_place_type<Decayed>::value,
int> = 0,
1528 std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1529 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1530 std::enable_if_t<std::is_constructible<T, Arg>::value,
int> = 0>
1531 inline constexpr variant(Arg &&arg) noexcept(
1532 std::is_nothrow_constructible<T, Arg>::value)
1533 : impl_(in_place_index_t<I>{}, std::forward<Arg>(arg)) {}
1538 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1539 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1540 inline explicit constexpr variant(
1541 in_place_index_t<I>,
1542 Args &&... args) noexcept(std::is_nothrow_constructible<T,
1544 : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1550 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1551 std::enable_if_t<std::is_constructible<T,
1552 std::initializer_list<Up> &,
1555 inline explicit constexpr variant(
1556 in_place_index_t<I>,
1557 std::initializer_list<Up> il,
1558 Args &&... args) noexcept(std::
1559 is_nothrow_constructible<
1561 std::initializer_list<Up> &,
1563 : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1568 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1569 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1570 inline explicit constexpr variant(
1572 Args &&... args) noexcept(std::is_nothrow_constructible<T,
1574 : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1580 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1581 std::enable_if_t<std::is_constructible<T,
1582 std::initializer_list<Up> &,
1585 inline explicit constexpr variant(
1587 std::initializer_list<Up> il,
1588 Args &&... args) noexcept(std::
1589 is_nothrow_constructible<
1591 std::initializer_list<Up> &,
1593 : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1595 ~variant() =
default;
1597 variant &operator=(
const variant &) =
default;
1598 variant &operator=(variant &&) =
default;
1600 template <
typename Arg,
1601 std::enable_if_t<!std::is_same<std::decay_t<Arg>, variant>::value,
1603 std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1604 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1605 std::enable_if_t<(std::is_assignable<T &, Arg>::value &&
1606 std::is_constructible<T, Arg>::value),
1608 inline variant &
operator=(Arg &&arg) noexcept(
1609 (std::is_nothrow_assignable<T &, Arg>::value &&
1610 std::is_nothrow_constructible<T, Arg>::value)) {
1611 impl_.template assign<I>(std::forward<Arg>(arg));
1618 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1619 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1620 inline T &emplace(Args &&... args) {
1621 return impl_.template emplace<I>(std::forward<Args>(args)...);
1628 typename T = detail_variant::type_pack_element_t<I, Ts...>,
1629 std::enable_if_t<std::is_constructible<T,
1630 std::initializer_list<Up> &,
1633 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1634 return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1640 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1641 std::enable_if_t<std::is_constructible<T, Args...>::value,
int> = 0>
1642 inline T &emplace(Args &&... args) {
1643 return impl_.template emplace<I>(std::forward<Args>(args)...);
1650 std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1651 std::enable_if_t<std::is_constructible<T,
1652 std::initializer_list<Up> &,
1655 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1656 return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1659 inline constexpr
bool valueless_by_exception() const noexcept {
1660 return impl_.valueless_by_exception();
1663 inline constexpr std::size_t index() const noexcept {
1664 return impl_.index();
1667 template <
bool Dummy =
true,
1669 detail_variant::all<Dummy,
1670 (detail_variant::dependent_type<std::is_move_constructible<Ts>,
1672 detail_variant::dependent_type<detail_variant::is_swappable<Ts>,
1673 Dummy>::value)...>::value,
1675 inline void swap(variant &that) noexcept(
1676 detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1677 detail_variant::is_nothrow_swappable<Ts>::value)...>::value) {
1678 impl_.swap(that.impl_);
1682 detail_variant::impl<Ts...> impl_;
1684 friend struct detail_variant::access::variant;
1685 friend struct detail_variant::visitation::variant;
1688 template <std::size_t I,
typename... Ts>
1689 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
1690 return v.index() == I;
1693 template <
typename T,
typename... Ts>
1694 inline constexpr
bool holds_alternative(
const variant<Ts...> &v) noexcept {
1695 return holds_alternative<detail_variant::find_index_checked<T, Ts...>::value>(v);
1698 namespace detail_variant {
1699 template <std::
size_t I,
typename V>
1700 struct generic_get_impl {
1701 constexpr generic_get_impl(
int) noexcept {}
1703 constexpr
auto&& operator()(V &&v)
const
1705 access::variant::get_alt<I>(std::forward<V>(v)).value)
1708 template <std::
size_t I,
typename V>
1709 inline constexpr
auto&& generic_get(V &&v)
1710 AUTO_REFREF_RETURN(generic_get_impl<I, V>(
1711 holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
1712 std::forward<V>(v)))
1715 template <std::size_t I,
typename... Ts>
1716 inline constexpr variant_alternative_t<I, variant<Ts...>> &
get(
1717 variant<Ts...> &v) {
1718 return detail_variant::generic_get<I>(v);
1721 template <std::size_t I,
typename... Ts>
1722 inline constexpr variant_alternative_t<I, variant<Ts...>> &&
get(
1723 variant<Ts...> &&v) {
1724 return detail_variant::generic_get<I>(std::move(v));
1727 template <std::size_t I,
typename... Ts>
1728 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &
get(
1729 const variant<Ts...> &v) {
1730 return detail_variant::generic_get<I>(v);
1733 template <std::size_t I,
typename... Ts>
1734 inline constexpr
const variant_alternative_t<I, variant<Ts...>> &&
get(
1735 const variant<Ts...> &&v) {
1736 return detail_variant::generic_get<I>(std::move(v));
1739 template <
typename T,
typename... Ts>
1740 inline constexpr T &
get(variant<Ts...> &v) {
1741 return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1744 template <
typename T,
typename... Ts>
1745 inline constexpr T &&
get(variant<Ts...> &&v) {
1746 return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1749 template <
typename T,
typename... Ts>
1750 inline constexpr
const T &
get(
const variant<Ts...> &v) {
1751 return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1754 template <
typename T,
typename... Ts>
1755 inline constexpr
const T &&
get(
const variant<Ts...> &&v) {
1756 return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1759 namespace detail_variant {
1761 template <std::
size_t I,
typename V>
1762 inline constexpr
auto* generic_get_if(V* v) noexcept {
1763 return v && holds_alternative<I>(*v)
1764 ? std::addressof(access::variant::get_alt<I>(*v).value)
1770 template <std::size_t I,
typename... Ts>
1771 inline constexpr std::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
1772 get_if(variant<Ts...> *v) noexcept {
1773 return detail_variant::generic_get_if<I>(v);
1776 template <std::size_t I,
typename... Ts>
1777 inline constexpr std::add_pointer_t<
1778 const variant_alternative_t<I, variant<Ts...>>>
1779 get_if(
const variant<Ts...> *v) noexcept {
1780 return detail_variant::generic_get_if<I>(v);
1783 template <
typename T,
typename... Ts>
1784 inline constexpr std::add_pointer_t<T>
1785 get_if(variant<Ts...> *v) noexcept {
1786 return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1789 template <
typename T,
typename... Ts>
1790 inline constexpr std::add_pointer_t<const T>
1791 get_if(
const variant<Ts...> *v) noexcept {
1792 return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1795 namespace detail_variant {
1796 template <
typename RelOp>
1797 struct convert_to_bool {
1798 template <
typename Lhs,
typename Rhs>
1799 inline constexpr
bool operator()(Lhs &&lhs, Rhs &&rhs)
const {
1800 static_assert(std::is_convertible<invoke_result_t<RelOp, Lhs, Rhs>,
1802 "relational operators must return a type"
1803 " implicitly convertible to bool");
1805 RelOp{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
1810 template <
typename... Ts>
1811 inline constexpr
bool operator==(
const variant<Ts...> &lhs,
1812 const variant<Ts...> &rhs) {
1813 using detail_variant::visitation::variant;
1814 using equal_to = detail_variant::convert_to_bool<std::equal_to<>>;
1815 if (lhs.index() != rhs.index())
return false;
1816 if (lhs.valueless_by_exception())
return true;
1817 return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
1820 template <
typename... Ts>
1821 inline constexpr
bool operator!=(
const variant<Ts...> &lhs,
1822 const variant<Ts...> &rhs) {
1823 using detail_variant::visitation::variant;
1824 using not_equal_to = detail_variant::convert_to_bool<std::not_equal_to<>>;
1825 if (lhs.index() != rhs.index())
return true;
1826 if (lhs.valueless_by_exception())
return false;
1827 return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
1830 template <
typename... Ts>
1831 inline constexpr
bool operator<(
const variant<Ts...> &lhs,
1832 const variant<Ts...> &rhs) {
1833 using detail_variant::visitation::variant;
1834 using less = detail_variant::convert_to_bool<std::less<>>;
1835 if (rhs.valueless_by_exception())
return false;
1836 if (lhs.valueless_by_exception())
return true;
1837 if (lhs.index() < rhs.index())
return true;
1838 if (lhs.index() > rhs.index())
return false;
1839 return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
1842 template <
typename... Ts>
1843 inline constexpr
bool operator>(
const variant<Ts...> &lhs,
1844 const variant<Ts...> &rhs) {
1845 using detail_variant::visitation::variant;
1846 using greater = detail_variant::convert_to_bool<std::greater<>>;
1847 if (lhs.valueless_by_exception())
return false;
1848 if (rhs.valueless_by_exception())
return true;
1849 if (lhs.index() > rhs.index())
return true;
1850 if (lhs.index() < rhs.index())
return false;
1851 return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
1854 template <
typename... Ts>
1855 inline constexpr
bool operator<=(
const variant<Ts...> &lhs,
1856 const variant<Ts...> &rhs) {
1857 using detail_variant::visitation::variant;
1858 using less_equal = detail_variant::convert_to_bool<std::less_equal<>>;
1859 if (lhs.valueless_by_exception())
return true;
1860 if (rhs.valueless_by_exception())
return false;
1861 if (lhs.index() < rhs.index())
return true;
1862 if (lhs.index() > rhs.index())
return false;
1863 return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
1866 template <
typename... Ts>
1867 inline constexpr
bool operator>=(
const variant<Ts...> &lhs,
1868 const variant<Ts...> &rhs) {
1869 using detail_variant::visitation::variant;
1870 using greater_equal = detail_variant::convert_to_bool<std::greater_equal<>>;
1871 if (rhs.valueless_by_exception())
return true;
1872 if (lhs.valueless_by_exception())
return false;
1873 if (lhs.index() > rhs.index())
return true;
1874 if (lhs.index() < rhs.index())
return false;
1875 return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
1878 namespace detail_variant {
1880 inline constexpr
bool any(std::initializer_list<bool> bs) {
1891 template <
typename Visitor,
typename... Vs>
1892 inline constexpr decltype(
auto)
visit(Visitor &&visitor, Vs &&... vs) {
1893 return (!detail_variant::any({vs.valueless_by_exception()...})
1895 : throw_bad_variant_access()),
1896 detail_variant::visitation::variant::visit_value(
1897 std::forward<Visitor>(visitor), std::forward<Vs>(vs)...);
1900 template <
typename... Ts>
1901 inline auto swap(variant<Ts...> &lhs,
1902 variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
1903 -> decltype(lhs.swap(rhs)) {
1907 namespace detail_variant {
1909 template <
typename T,
typename...>
1910 using enabled_type = T;
1914 template <
typename H,
typename K>
1915 constexpr
bool meets_requirements() noexcept {
1916 return std::is_copy_constructible<H>::value &&
1917 std::is_move_constructible<H>::value &&
1918 is_invocable_r<std::size_t, H, const K &>::value;
1921 template <
typename K>
1922 constexpr
bool is_enabled() noexcept {
1923 using H = std::hash<K>;
1924 return meets_requirements<H, K>() &&
1925 std::is_default_constructible<H>::value &&
1926 std::is_copy_assignable<H>::value &&
1927 std::is_move_assignable<H>::value;
1934 #undef AUTO_REFREF_RETURN
1940 template <
typename... Ts>
1941 struct hash<
gul14::detail_variant::enabled_type<
1942 gul14::variant<Ts...>,
1943 std::enable_if_t<gul14::detail_variant::all<gul14::detail_variant::hash::is_enabled<
1944 std::remove_const_t<Ts>>()...>::value>>> {
1946 using result_type = std::size_t;
1948 inline result_type operator()(
const argument_type &v)
const {
1949 using gul14::detail_variant::visitation::variant;
1950 std::size_t result =
1951 v.valueless_by_exception()
1953 : variant::visit_alt(
1954 [](
const auto &alt) {
1955 using alt_type = std::decay_t<decltype(alt)>;
1956 using value_type = std::remove_const_t<
1957 typename alt_type::value_type>;
1958 return hash<value_type>{}(alt.value);
1961 return hash_combine(result, hash<std::size_t>{}(v.index()));
1965 static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
1966 return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
The exception thrown if the wrong type is accessed on a gul14::variant.
Definition: variant.h:50
A "type-safe union".
Definition: variant.h:72
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
typename invoke_result< F, Args... >::type invoke_result_t
A shortcut for invoke_result<...>::type.
Definition: traits.h:248
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Invoke a callable object f with the given arguments.
Definition: traits.h:201
detail_invocable::is_invocable< void, F, Args... > is_invocable
A type trait that checks whether a callable object of type F can be invoked with the given arguments.
Definition: traits.h:282
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:139
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:106
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.