3 // Copyright Michael Park, 2015-2017
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 #ifndef MPARK_VARIANT_HPP
9 #define MPARK_VARIANT_HPP
16 // 20.7.2, class template variant
17 template <class... Types>
21 // 20.7.2.1, constructors
22 constexpr variant() noexcept(see below);
23 variant(const variant&);
24 variant(variant&&) noexcept(see below);
26 template <class T> constexpr variant(T&&) noexcept(see below);
28 template <class T, class... Args>
29 constexpr explicit variant(in_place_type_t<T>, Args&&...);
31 template <class T, class U, class... Args>
32 constexpr explicit variant(
33 in_place_type_t<T>, initializer_list<U>, Args&&...);
35 template <size_t I, class... Args>
36 constexpr explicit variant(in_place_index_t<I>, Args&&...);
38 template <size_t I, class U, class... Args>
39 constexpr explicit variant(
40 in_place_index_t<I>, initializer_list<U>, Args&&...);
42 // 20.7.2.2, destructor
45 // 20.7.2.3, assignment
46 variant& operator=(const variant&);
47 variant& operator=(variant&&) noexcept(see below);
49 template <class T> variant& operator=(T&&) noexcept(see below);
51 // 20.7.2.4, modifiers
52 template <class T, class... Args>
53 T& emplace(Args&&...);
55 template <class T, class U, class... Args>
56 T& emplace(initializer_list<U>, Args&&...);
58 template <size_t I, class... Args>
59 variant_alternative<I, variant>& emplace(Args&&...);
61 template <size_t I, class U, class... Args>
62 variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...);
64 // 20.7.2.5, value status
65 constexpr bool valueless_by_exception() const noexcept;
66 constexpr size_t index() const noexcept;
69 void swap(variant&) noexcept(see below);
72 // 20.7.3, variant helper classes
73 template <class T> struct variant_size; // undefined
76 constexpr size_t variant_size_v = variant_size<T>::value;
78 template <class T> struct variant_size<const T>;
79 template <class T> struct variant_size<volatile T>;
80 template <class T> struct variant_size<const volatile T>;
82 template <class... Types>
83 struct variant_size<variant<Types...>>;
85 template <size_t I, class T> struct variant_alternative; // undefined
87 template <size_t I, class T>
88 using variant_alternative_t = typename variant_alternative<I, T>::type;
90 template <size_t I, class T> struct variant_alternative<I, const T>;
91 template <size_t I, class T> struct variant_alternative<I, volatile T>;
92 template <size_t I, class T> struct variant_alternative<I, const volatile T>;
94 template <size_t I, class... Types>
95 struct variant_alternative<I, variant<Types...>>;
97 constexpr size_t variant_npos = -1;
99 // 20.7.4, value access
100 template <class T, class... Types>
101 constexpr bool holds_alternative(const variant<Types...>&) noexcept;
103 template <size_t I, class... Types>
104 constexpr variant_alternative_t<I, variant<Types...>>&
105 get(variant<Types...>&);
107 template <size_t I, class... Types>
108 constexpr variant_alternative_t<I, variant<Types...>>&&
109 get(variant<Types...>&&);
111 template <size_t I, class... Types>
112 constexpr variant_alternative_t<I, variant<Types...>> const&
113 get(const variant<Types...>&);
115 template <size_t I, class... Types>
116 constexpr variant_alternative_t<I, variant<Types...>> const&&
117 get(const variant<Types...>&&);
119 template <class T, class... Types>
120 constexpr T& get(variant<Types...>&);
122 template <class T, class... Types>
123 constexpr T&& get(variant<Types...>&&);
125 template <class T, class... Types>
126 constexpr const T& get(const variant<Types...>&);
128 template <class T, class... Types>
129 constexpr const T&& get(const variant<Types...>&&);
131 template <size_t I, class... Types>
132 constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
133 get_if(variant<Types...>*) noexcept;
135 template <size_t I, class... Types>
136 constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
137 get_if(const variant<Types...>*) noexcept;
139 template <class T, class... Types>
140 constexpr add_pointer_t<T>
141 get_if(variant<Types...>*) noexcept;
143 template <class T, class... Types>
144 constexpr add_pointer_t<const T>
145 get_if(const variant<Types...>*) noexcept;
147 // 20.7.5, relational operators
148 template <class... Types>
149 constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
151 template <class... Types>
152 constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
154 template <class... Types>
155 constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
157 template <class... Types>
158 constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
160 template <class... Types>
161 constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
163 template <class... Types>
164 constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
166 // 20.7.6, visitation
167 template <class Visitor, class... Variants>
168 constexpr see below visit(Visitor&&, Variants&&...);
170 // 20.7.7, class monostate
173 // 20.7.8, monostate relational operators
174 constexpr bool operator<(monostate, monostate) noexcept;
175 constexpr bool operator>(monostate, monostate) noexcept;
176 constexpr bool operator<=(monostate, monostate) noexcept;
177 constexpr bool operator>=(monostate, monostate) noexcept;
178 constexpr bool operator==(monostate, monostate) noexcept;
179 constexpr bool operator!=(monostate, monostate) noexcept;
181 // 20.7.9, specialized algorithms
182 template <class... Types>
183 void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
185 // 20.7.10, class bad_variant_access
186 class bad_variant_access;
188 // 20.7.11, hash support
189 template <class T> struct hash;
190 template <class... Types> struct hash<variant<Types...>>;
191 template <> struct hash<monostate>;
199 #include <functional>
200 #include <initializer_list>
202 #include <type_traits>
205 #include "config.hpp"
206 #include "in_place.hpp"
211 #ifdef MPARK_RETURN_TYPE_DEDUCTION
214 #define AUTO_RETURN(...) { return __VA_ARGS__; }
216 #define AUTO_REFREF auto &&
217 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
219 #define DECLTYPE_AUTO decltype(auto)
220 #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }
225 #define AUTO_RETURN(...) \
226 -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
228 #define AUTO_REFREF auto
229 #define AUTO_REFREF_RETURN(...) \
230 -> decltype((__VA_ARGS__)) { \
231 static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
232 return __VA_ARGS__; \
235 #define DECLTYPE_AUTO auto
236 #define DECLTYPE_AUTO_RETURN(...) \
237 -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
241 class bad_variant_access
: public std::exception
{
243 virtual const char *what() const noexcept
{ return "bad_variant_access"; }
246 [[noreturn
]] inline void throw_bad_variant_access() {
247 #ifdef MPARK_EXCEPTIONS
248 throw bad_variant_access
{};
251 #ifdef MPARK_BUILTIN_UNREACHABLE
252 __builtin_unreachable();
257 template <typename
... Ts
>
260 template <typename T
>
263 #ifdef MPARK_VARIABLE_TEMPLATES
264 template <typename T
>
265 constexpr std::size_t variant_size_v
= variant_size
<T
>::value
;
268 template <typename T
>
269 struct variant_size
<const T
> : variant_size
<T
> {};
271 template <typename T
>
272 struct variant_size
<volatile T
> : variant_size
<T
> {};
274 template <typename T
>
275 struct variant_size
<const volatile T
> : variant_size
<T
> {};
277 template <typename
... Ts
>
278 struct variant_size
<variant
<Ts
...>> : lib::size_constant
<sizeof...(Ts
)> {};
280 template <std::size_t I
, typename T
>
281 struct variant_alternative
;
283 template <std::size_t I
, typename T
>
284 using variant_alternative_t
= typename variant_alternative
<I
, T
>::type
;
286 template <std::size_t I
, typename T
>
287 struct variant_alternative
<I
, const T
>
288 : std::add_const
<variant_alternative_t
<I
, T
>> {};
290 template <std::size_t I
, typename T
>
291 struct variant_alternative
<I
, volatile T
>
292 : std::add_volatile
<variant_alternative_t
<I
, T
>> {};
294 template <std::size_t I
, typename T
>
295 struct variant_alternative
<I
, const volatile T
>
296 : std::add_cv
<variant_alternative_t
<I
, T
>> {};
298 template <std::size_t I
, typename
... Ts
>
299 struct variant_alternative
<I
, variant
<Ts
...>> {
300 static_assert(I
< sizeof...(Ts
),
301 "Index out of bounds in std::variant_alternative<>");
302 using type
= lib::type_pack_element_t
<I
, Ts
...>;
305 constexpr std::size_t variant_npos
= static_cast<std::size_t>(-1);
309 constexpr std::size_t not_found
= static_cast<std::size_t>(-1);
310 constexpr std::size_t ambiguous
= static_cast<std::size_t>(-2);
312 #ifdef MPARK_CPP14_CONSTEXPR
313 template <typename T
, typename
... Ts
>
314 inline constexpr std::size_t find_index() {
315 constexpr lib::array
<bool, sizeof...(Ts
)> matches
= {
316 {std::is_same
<T
, Ts
>::value
...}
318 std::size_t result
= not_found
;
319 for (std::size_t i
= 0; i
< sizeof...(Ts
); ++i
) {
321 if (result
!= not_found
) {
330 inline constexpr std::size_t find_index_impl(std::size_t result
,
335 template <typename
... Bs
>
336 inline constexpr std::size_t find_index_impl(std::size_t result
,
340 return b
? (result
!= not_found
? ambiguous
341 : find_index_impl(idx
, idx
+ 1, bs
...))
342 : find_index_impl(result
, idx
+ 1, bs
...);
345 template <typename T
, typename
... Ts
>
346 inline constexpr std::size_t find_index() {
347 return find_index_impl(not_found
, 0, std::is_same
<T
, Ts
>::value
...);
351 template <std::size_t I
>
352 using find_index_sfinae_impl
=
353 lib::enable_if_t
<I
!= not_found
&& I
!= ambiguous
,
354 lib::size_constant
<I
>>;
356 template <typename T
, typename
... Ts
>
357 using find_index_sfinae
= find_index_sfinae_impl
<find_index
<T
, Ts
...>()>;
359 template <std::size_t I
>
360 struct find_index_checked_impl
: lib::size_constant
<I
> {
361 static_assert(I
!= not_found
, "the specified type is not found.");
362 static_assert(I
!= ambiguous
, "the specified type is ambiguous.");
365 template <typename T
, typename
... Ts
>
366 using find_index_checked
= find_index_checked_impl
<find_index
<T
, Ts
...>()>;
368 struct valueless_t
{};
370 enum class Trait
{ TriviallyAvailable
, Available
, Unavailable
};
372 template <typename T
,
373 template <typename
> class IsTriviallyAvailable
,
374 template <typename
> class IsAvailable
>
375 inline constexpr Trait
trait() {
376 return IsTriviallyAvailable
<T
>::value
377 ? Trait::TriviallyAvailable
378 : IsAvailable
<T
>::value
? Trait::Available
379 : Trait::Unavailable
;
382 #ifdef MPARK_CPP14_CONSTEXPR
383 template <typename
... Traits
>
384 inline constexpr Trait
common_trait(Traits
... traits
) {
385 Trait result
= Trait::TriviallyAvailable
;
386 for (Trait t
: {traits
...}) {
387 if (static_cast<int>(t
) > static_cast<int>(result
)) {
394 inline constexpr Trait
common_trait_impl(Trait result
) { return result
; }
396 template <typename
... Traits
>
397 inline constexpr Trait
common_trait_impl(Trait result
,
400 return static_cast<int>(t
) > static_cast<int>(result
)
401 ? common_trait_impl(t
, ts
...)
402 : common_trait_impl(result
, ts
...);
405 template <typename
... Traits
>
406 inline constexpr Trait
common_trait(Traits
... ts
) {
407 return common_trait_impl(Trait::TriviallyAvailable
, ts
...);
411 template <typename
... Ts
>
413 static constexpr Trait copy_constructible_trait
=
414 common_trait(trait
<Ts
,
415 lib::is_trivially_copy_constructible
,
416 std::is_copy_constructible
>()...);
418 static constexpr Trait move_constructible_trait
=
419 common_trait(trait
<Ts
,
420 lib::is_trivially_move_constructible
,
421 std::is_move_constructible
>()...);
423 static constexpr Trait copy_assignable_trait
=
424 common_trait(copy_constructible_trait
,
426 lib::is_trivially_copy_assignable
,
427 std::is_copy_assignable
>()...);
429 static constexpr Trait move_assignable_trait
=
430 common_trait(move_constructible_trait
,
432 lib::is_trivially_move_assignable
,
433 std::is_move_assignable
>()...);
435 static constexpr Trait destructible_trait
=
436 common_trait(trait
<Ts
,
437 std::is_trivially_destructible
,
438 std::is_destructible
>()...);
443 struct recursive_union
{
444 #ifdef MPARK_RETURN_TYPE_DEDUCTION
445 template <typename V
>
446 inline static constexpr auto &&get_alt(V
&&v
, in_place_index_t
<0>) {
447 return lib::forward
<V
>(v
).head_
;
450 template <typename V
, std::size_t I
>
451 inline static constexpr auto &&get_alt(V
&&v
, in_place_index_t
<I
>) {
452 return get_alt(lib::forward
<V
>(v
).tail_
, in_place_index_t
<I
- 1>{});
455 template <std::size_t I
, bool Dummy
= true>
456 struct get_alt_impl
{
457 template <typename V
>
458 inline constexpr AUTO_REFREF
operator()(V
&&v
) const
459 AUTO_REFREF_RETURN(get_alt_impl
<I
- 1>{}(lib::forward
<V
>(v
).tail_
))
462 template <bool Dummy
>
463 struct get_alt_impl
<0, Dummy
> {
464 template <typename V
>
465 inline constexpr AUTO_REFREF
operator()(V
&&v
) const
466 AUTO_REFREF_RETURN(lib::forward
<V
>(v
).head_
)
469 template <typename V
, std::size_t I
>
470 inline static constexpr AUTO_REFREF
get_alt(V
&&v
, in_place_index_t
<I
>)
471 AUTO_REFREF_RETURN(get_alt_impl
<I
>{}(lib::forward
<V
>(v
)))
476 template <std::size_t I
, typename V
>
477 inline static constexpr AUTO_REFREF
get_alt(V
&&v
)
478 AUTO_REFREF_RETURN(recursive_union::get_alt(
479 data(lib::forward
<V
>(v
)), in_place_index_t
<I
>{}))
483 template <std::size_t I
, typename V
>
484 inline static constexpr AUTO_REFREF
get_alt(V
&&v
)
485 AUTO_REFREF_RETURN(base::get_alt
<I
>(lib::forward
<V
>(v
).impl_
))
488 } // namespace access
490 namespace visitation
{
494 template <typename T
>
495 inline static constexpr const T
&at(const T
&elem
) {
499 template <typename T
, std::size_t N
, typename
... Is
>
500 inline static constexpr const lib::remove_all_extents_t
<T
> &at(
501 const lib::array
<T
, N
> &elems
, std::size_t i
, Is
... is
) {
502 return at(elems
[i
], is
...);
505 template <typename F
, typename
... Fs
>
506 inline static constexpr int visit_visitor_return_type_check() {
507 static_assert(lib::all
<std::is_same
<F
, Fs
>::value
...>::value
,
508 "`mpark::visit` requires the visitor to have a single "
513 template <typename
... Fs
>
514 inline static constexpr lib::array
<
515 lib::common_type_t
<lib::decay_t
<Fs
>...>,
517 make_farray(Fs
&&... fs
) {
518 using result
= lib::array
<lib::common_type_t
<lib::decay_t
<Fs
>...>,
520 return visit_visitor_return_type_check
<lib::decay_t
<Fs
>...>(),
521 result
{{lib::forward
<Fs
>(fs
)...}};
524 template <std::size_t... Is
>
526 template <typename F
, typename
... Vs
>
528 inline static constexpr DECLTYPE_AUTO
dispatch(F f
, Vs
... vs
)
529 DECLTYPE_AUTO_RETURN(lib::invoke(
531 access::base::get_alt
<Is
>(static_cast<Vs
>(vs
))...))
535 template <typename F
, typename
... Vs
, std::size_t... Is
>
536 inline static constexpr AUTO
make_dispatch(lib::index_sequence
<Is
...>)
537 AUTO_RETURN(&dispatcher
<Is
...>::template impl
<F
, Vs
...>::dispatch
)
539 template <std::size_t I
, typename F
, typename
... Vs
>
540 inline static constexpr AUTO
make_fdiagonal_impl()
541 AUTO_RETURN(make_dispatch
<F
, Vs
...>(
542 lib::index_sequence
<lib::indexed_type
<I
, Vs
>::value
...>{}))
544 template <typename F
, typename
... Vs
, std::size_t... Is
>
545 inline static constexpr AUTO
make_fdiagonal_impl(
546 lib::index_sequence
<Is
...>)
547 AUTO_RETURN(make_farray(make_fdiagonal_impl
<Is
, F
, Vs
...>()...))
549 template <typename F
, typename V
, typename
... Vs
>
550 inline static constexpr /* auto * */ auto make_fdiagonal()
551 -> decltype(make_fdiagonal_impl
<F
, V
, Vs
...>(
552 lib::make_index_sequence
<lib::decay_t
<V
>::size()>{})) {
553 static_assert(lib::all
<(lib::decay_t
<V
>::size() ==
554 lib::decay_t
<Vs
>::size())...>::value
,
555 "all of the variants must be the same size.");
556 return make_fdiagonal_impl
<F
, V
, Vs
...>(
557 lib::make_index_sequence
<lib::decay_t
<V
>::size()>{});
560 #ifdef MPARK_RETURN_TYPE_DEDUCTION
561 template <typename F
, typename
... Vs
, std::size_t... Is
>
562 inline static constexpr auto make_fmatrix_impl(
563 lib::index_sequence
<Is
...> is
) {
564 return make_dispatch
<F
, Vs
...>(is
);
567 template <typename F
,
572 inline static constexpr auto make_fmatrix_impl(
573 lib::index_sequence
<Is
...>, lib::index_sequence
<Js
...>, Ls
... ls
) {
574 return make_farray(make_fmatrix_impl
<F
, Vs
...>(
575 lib::index_sequence
<Is
..., Js
>{}, ls
...)...);
578 template <typename F
, typename
... Vs
>
579 inline static constexpr auto make_fmatrix() {
580 return make_fmatrix_impl
<F
, Vs
...>(
581 lib::index_sequence
<>{},
582 lib::make_index_sequence
<lib::decay_t
<Vs
>::size()>{}...);
585 template <typename F
, typename
... Vs
>
586 struct make_fmatrix_impl
{
587 template <typename
...>
590 template <std::size_t... Is
>
591 struct impl
<lib::index_sequence
<Is
...>> {
592 inline constexpr AUTO
operator()() const
594 make_dispatch
<F
, Vs
...>(lib::index_sequence
<Is
...>{}))
597 template <std::size_t... Is
, std::size_t... Js
, typename
... Ls
>
598 struct impl
<lib::index_sequence
<Is
...>,
599 lib::index_sequence
<Js
...>,
601 inline constexpr AUTO
operator()() const
602 AUTO_RETURN(make_farray(
603 impl
<lib::index_sequence
<Is
..., Js
>, Ls
...>{}()...))
607 template <typename F
, typename
... Vs
>
608 inline static constexpr AUTO
make_fmatrix()
610 typename make_fmatrix_impl
<F
, Vs
...>::template impl
<
611 lib::index_sequence
<>,
612 lib::make_index_sequence
<lib::decay_t
<Vs
>::size()>...>{}())
616 template <typename Visitor
, typename
... Vs
>
617 inline static constexpr DECLTYPE_AUTO
visit_alt_at(std::size_t index
,
620 DECLTYPE_AUTO_RETURN(
621 at(make_fdiagonal
<Visitor
&&,
622 decltype(as_base(lib::forward
<Vs
>(vs
)))...>(),
623 index
)(lib::forward
<Visitor
>(visitor
),
624 as_base(lib::forward
<Vs
>(vs
))...))
626 template <typename Visitor
, typename
... Vs
>
627 inline static constexpr DECLTYPE_AUTO
visit_alt(Visitor
&&visitor
,
629 DECLTYPE_AUTO_RETURN(
630 at(make_fmatrix
<Visitor
&&,
631 decltype(as_base(lib::forward
<Vs
>(vs
)))...>(),
632 vs
.index()...)(lib::forward
<Visitor
>(visitor
),
633 as_base(lib::forward
<Vs
>(vs
))...))
638 template <typename Visitor
, typename
... Values
>
639 struct visit_exhaustive_visitor_check
{
641 lib::is_invocable
<Visitor
, Values
...>::value
,
642 "`mpark::visit` requires the visitor to be exhaustive.");
645 #pragma warning(push)
646 #pragma warning(disable : 4100)
648 inline constexpr DECLTYPE_AUTO
operator()(Visitor
&&visitor
,
649 Values
&&... values
) const
650 DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward
<Visitor
>(visitor
),
651 lib::forward
<Values
>(values
)...))
657 template <typename Visitor
>
658 struct value_visitor
{
661 template <typename
... Alts
>
662 inline constexpr DECLTYPE_AUTO
operator()(Alts
&&... alts
) const
663 DECLTYPE_AUTO_RETURN(
664 visit_exhaustive_visitor_check
<
666 decltype((lib::forward
<Alts
>(alts
).value
))...>{}(
667 lib::forward
<Visitor
>(visitor_
),
668 lib::forward
<Alts
>(alts
).value
...))
671 template <typename Visitor
>
672 inline static constexpr AUTO
make_value_visitor(Visitor
&&visitor
)
673 AUTO_RETURN(value_visitor
<Visitor
>{lib::forward
<Visitor
>(visitor
)})
676 template <typename Visitor
, typename
... Vs
>
677 inline static constexpr DECLTYPE_AUTO
visit_alt_at(std::size_t index
,
680 DECLTYPE_AUTO_RETURN(
681 base::visit_alt_at(index
,
682 lib::forward
<Visitor
>(visitor
),
683 lib::forward
<Vs
>(vs
).impl_
...))
685 template <typename Visitor
, typename
... Vs
>
686 inline static constexpr DECLTYPE_AUTO
visit_alt(Visitor
&&visitor
,
688 DECLTYPE_AUTO_RETURN(base::visit_alt(lib::forward
<Visitor
>(visitor
),
689 lib::forward
<Vs
>(vs
).impl_
...))
691 template <typename Visitor
, typename
... Vs
>
692 inline static constexpr DECLTYPE_AUTO
visit_value_at(std::size_t index
,
695 DECLTYPE_AUTO_RETURN(
697 make_value_visitor(lib::forward
<Visitor
>(visitor
)),
698 lib::forward
<Vs
>(vs
)...))
700 template <typename Visitor
, typename
... Vs
>
701 inline static constexpr DECLTYPE_AUTO
visit_value(Visitor
&&visitor
,
703 DECLTYPE_AUTO_RETURN(
704 visit_alt(make_value_visitor(lib::forward
<Visitor
>(visitor
)),
705 lib::forward
<Vs
>(vs
)...))
708 } // namespace visitation
710 template <std::size_t Index
, typename T
>
712 using value_type
= T
;
715 #pragma warning(push)
716 #pragma warning(disable : 4244)
718 template <typename
... Args
>
719 inline explicit constexpr alt(in_place_t
, Args
&&... args
)
720 : value(lib::forward
<Args
>(args
)...) {}
728 template <Trait DestructibleTrait
, std::size_t Index
, typename
... Ts
>
729 union recursive_union
;
731 template <Trait DestructibleTrait
, std::size_t Index
>
732 union recursive_union
<DestructibleTrait
, Index
> {};
734 #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
735 template <std::size_t Index, typename T, typename... Ts> \
736 union recursive_union<destructible_trait, Index, T, Ts...> { \
738 inline explicit constexpr recursive_union(valueless_t) noexcept \
741 template <typename... Args> \
742 inline explicit constexpr recursive_union(in_place_index_t<0>, \
744 : head_(in_place_t{}, lib::forward<Args>(args)...) {} \
746 template <std::size_t I, typename... Args> \
747 inline explicit constexpr recursive_union(in_place_index_t<I>, \
749 : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \
751 recursive_union(const recursive_union &) = default; \
752 recursive_union(recursive_union &&) = default; \
756 recursive_union &operator=(const recursive_union &) = default; \
757 recursive_union &operator=(recursive_union &&) = default; \
761 alt<Index, T> head_; \
762 recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
764 friend struct access::recursive_union; \
767 MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable
,
768 ~recursive_union() = default;);
769 MPARK_VARIANT_RECURSIVE_UNION(Trait::Available
,
770 ~recursive_union() {});
771 MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable
,
772 ~recursive_union() = delete;);
774 #undef MPARK_VARIANT_RECURSIVE_UNION
776 using index_t
= unsigned int;
778 template <Trait DestructibleTrait
, typename
... Ts
>
781 inline explicit constexpr base(valueless_t tag
) noexcept
782 : data_(tag
), index_(static_cast<index_t
>(-1)) {}
784 template <std::size_t I
, typename
... Args
>
785 inline explicit constexpr base(in_place_index_t
<I
>, Args
&&... args
)
786 : data_(in_place_index_t
<I
>{}, lib::forward
<Args
>(args
)...),
789 inline constexpr bool valueless_by_exception() const noexcept
{
790 return index_
== static_cast<index_t
>(-1);
793 inline constexpr std::size_t index() const noexcept
{
794 return valueless_by_exception() ? variant_npos
: index_
;
798 using data_t
= recursive_union
<DestructibleTrait
, 0, Ts
...>;
800 friend inline constexpr base
&as_base(base
&b
) { return b
; }
801 friend inline constexpr const base
&as_base(const base
&b
) { return b
; }
802 friend inline constexpr base
&&as_base(base
&&b
) { return lib::move(b
); }
803 friend inline constexpr const base
&&as_base(const base
&&b
) { return lib::move(b
); }
805 friend inline constexpr data_t
&data(base
&b
) { return b
.data_
; }
806 friend inline constexpr const data_t
&data(const base
&b
) { return b
.data_
; }
807 friend inline constexpr data_t
&&data(base
&&b
) { return lib::move(b
).data_
; }
808 friend inline constexpr const data_t
&&data(const base
&&b
) { return lib::move(b
).data_
; }
810 inline static constexpr std::size_t size() { return sizeof...(Ts
); }
815 friend struct access::base
;
816 friend struct visitation::base
;
821 #pragma warning(push)
822 #pragma warning(disable : 4100)
824 template <typename Alt
>
825 inline void operator()(Alt
&alt
) const noexcept
{ alt
.~Alt(); }
831 #if defined(_MSC_VER) && _MSC_VER < 1910
832 #define INHERITING_CTOR(type, base) \
833 template <typename... Args> \
834 inline explicit constexpr type(Args &&... args) \
835 : base(lib::forward<Args>(args)...) {}
837 #define INHERITING_CTOR(type, base) using base::base;
840 template <typename Traits
, Trait
= Traits::destructible_trait
>
843 #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
844 template <typename... Ts> \
845 class destructor<traits<Ts...>, destructible_trait> \
846 : public base<destructible_trait, Ts...> { \
847 using super = base<destructible_trait, Ts...>; \
850 INHERITING_CTOR(destructor, super) \
851 using super::operator=; \
853 destructor(const destructor &) = default; \
854 destructor(destructor &&) = default; \
856 destructor &operator=(const destructor &) = default; \
857 destructor &operator=(destructor &&) = default; \
863 MPARK_VARIANT_DESTRUCTOR(
864 Trait::TriviallyAvailable
,
865 ~destructor() = default;,
866 inline void destroy() noexcept
{
867 this->index_
= static_cast<index_t
>(-1);
870 MPARK_VARIANT_DESTRUCTOR(
872 ~destructor() { destroy(); },
873 inline void destroy() noexcept
{
874 if (!this->valueless_by_exception()) {
875 visitation::base::visit_alt(dtor
{}, *this);
877 this->index_
= static_cast<index_t
>(-1);
880 MPARK_VARIANT_DESTRUCTOR(
882 ~destructor() = delete;,
883 inline void destroy() noexcept
= delete;);
885 #undef MPARK_VARIANT_DESTRUCTOR
887 template <typename Traits
>
888 class constructor
: public destructor
<Traits
> {
889 using super
= destructor
<Traits
>;
892 INHERITING_CTOR(constructor
, super
)
893 using super::operator=;
896 #ifndef MPARK_GENERIC_LAMBDAS
898 template <typename LhsAlt
, typename RhsAlt
>
899 inline void operator()(LhsAlt
&lhs_alt
, RhsAlt
&&rhs_alt
) const {
900 constructor::construct_alt(lhs_alt
,
901 lib::forward
<RhsAlt
>(rhs_alt
).value
);
906 template <std::size_t I
, typename T
, typename
... Args
>
907 inline static T
&construct_alt(alt
<I
, T
> &a
, Args
&&... args
) {
908 ::new (static_cast<void *>(lib::addressof(a
)))
909 alt
<I
, T
>(in_place_t
{}, lib::forward
<Args
>(args
)...);
913 template <typename Rhs
>
914 inline static void generic_construct(constructor
&lhs
, Rhs
&&rhs
) {
916 if (!rhs
.valueless_by_exception()) {
917 visitation::base::visit_alt_at(
919 #ifdef MPARK_GENERIC_LAMBDAS
920 [](auto &lhs_alt
, auto &&rhs_alt
) {
921 constructor::construct_alt(
922 lhs_alt
, lib::forward
<decltype(rhs_alt
)>(rhs_alt
).value
);
929 lib::forward
<Rhs
>(rhs
));
930 lhs
.index_
= rhs
.index_
;
935 template <typename Traits
, Trait
= Traits::move_constructible_trait
>
936 class move_constructor
;
938 #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
939 template <typename... Ts> \
940 class move_constructor<traits<Ts...>, move_constructible_trait> \
941 : public constructor<traits<Ts...>> { \
942 using super = constructor<traits<Ts...>>; \
945 INHERITING_CTOR(move_constructor, super) \
946 using super::operator=; \
948 move_constructor(const move_constructor &) = default; \
950 ~move_constructor() = default; \
951 move_constructor &operator=(const move_constructor &) = default; \
952 move_constructor &operator=(move_constructor &&) = default; \
955 MPARK_VARIANT_MOVE_CONSTRUCTOR(
956 Trait::TriviallyAvailable
,
957 move_constructor(move_constructor
&&that
) = default;);
959 MPARK_VARIANT_MOVE_CONSTRUCTOR(
961 move_constructor(move_constructor
&&that
) noexcept(
962 lib::all
<std::is_nothrow_move_constructible
<Ts
>::value
...>::value
)
963 : move_constructor(valueless_t
{}) {
964 this->generic_construct(*this, lib::move(that
));
967 MPARK_VARIANT_MOVE_CONSTRUCTOR(
969 move_constructor(move_constructor
&&) = delete;);
971 #undef MPARK_VARIANT_MOVE_CONSTRUCTOR
973 template <typename Traits
, Trait
= Traits::copy_constructible_trait
>
974 class copy_constructor
;
976 #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
977 template <typename... Ts> \
978 class copy_constructor<traits<Ts...>, copy_constructible_trait> \
979 : public move_constructor<traits<Ts...>> { \
980 using super = move_constructor<traits<Ts...>>; \
983 INHERITING_CTOR(copy_constructor, super) \
984 using super::operator=; \
987 copy_constructor(copy_constructor &&) = default; \
988 ~copy_constructor() = default; \
989 copy_constructor &operator=(const copy_constructor &) = default; \
990 copy_constructor &operator=(copy_constructor &&) = default; \
993 MPARK_VARIANT_COPY_CONSTRUCTOR(
994 Trait::TriviallyAvailable
,
995 copy_constructor(const copy_constructor
&that
) = default;);
997 MPARK_VARIANT_COPY_CONSTRUCTOR(
999 copy_constructor(const copy_constructor
&that
)
1000 : copy_constructor(valueless_t
{}) {
1001 this->generic_construct(*this, that
);
1004 MPARK_VARIANT_COPY_CONSTRUCTOR(
1006 copy_constructor(const copy_constructor
&) = delete;);
1008 #undef MPARK_VARIANT_COPY_CONSTRUCTOR
1010 template <typename Traits
>
1011 class assignment
: public copy_constructor
<Traits
> {
1012 using super
= copy_constructor
<Traits
>;
1015 INHERITING_CTOR(assignment
, super
)
1016 using super::operator=;
1018 template <std::size_t I
, typename
... Args
>
1019 inline /* auto & */ auto emplace(Args
&&... args
)
1020 -> decltype(this->construct_alt(access::base::get_alt
<I
>(*this),
1021 lib::forward
<Args
>(args
)...)) {
1023 auto &result
= this->construct_alt(access::base::get_alt
<I
>(*this),
1024 lib::forward
<Args
>(args
)...);
1030 #ifndef MPARK_GENERIC_LAMBDAS
1031 template <typename That
>
1033 template <typename ThisAlt
, typename ThatAlt
>
1034 inline void operator()(ThisAlt
&this_alt
, ThatAlt
&&that_alt
) const {
1035 self
->assign_alt(this_alt
, lib::forward
<ThatAlt
>(that_alt
).value
);
1041 template <std::size_t I
, typename T
, typename Arg
>
1042 inline void assign_alt(alt
<I
, T
> &a
, Arg
&&arg
) {
1043 if (this->index() == I
) {
1045 #pragma warning(push)
1046 #pragma warning(disable : 4244)
1048 a
.value
= lib::forward
<Arg
>(arg
);
1050 #pragma warning(pop)
1054 void operator()(std::true_type
) const {
1055 this_
->emplace
<I
>(lib::forward
<Arg
>(arg_
));
1057 void operator()(std::false_type
) const {
1058 this_
->emplace
<I
>(T(lib::forward
<Arg
>(arg_
)));
1062 } impl
{this, lib::forward
<Arg
>(arg
)};
1063 impl(lib::bool_constant
<
1064 std::is_nothrow_constructible
<T
, Arg
>::value
||
1065 !std::is_nothrow_move_constructible
<T
>::value
>{});
1069 template <typename That
>
1070 inline void generic_assign(That
&&that
) {
1071 if (this->valueless_by_exception() && that
.valueless_by_exception()) {
1073 } else if (that
.valueless_by_exception()) {
1076 visitation::base::visit_alt_at(
1078 #ifdef MPARK_GENERIC_LAMBDAS
1079 [this](auto &this_alt
, auto &&that_alt
) {
1081 this_alt
, lib::forward
<decltype(that_alt
)>(that_alt
).value
);
1084 assigner
<That
>{this}
1088 lib::forward
<That
>(that
));
1093 template <typename Traits
, Trait
= Traits::move_assignable_trait
>
1094 class move_assignment
;
1096 #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
1097 template <typename... Ts> \
1098 class move_assignment<traits<Ts...>, move_assignable_trait> \
1099 : public assignment<traits<Ts...>> { \
1100 using super = assignment<traits<Ts...>>; \
1103 INHERITING_CTOR(move_assignment, super) \
1104 using super::operator=; \
1106 move_assignment(const move_assignment &) = default; \
1107 move_assignment(move_assignment &&) = default; \
1108 ~move_assignment() = default; \
1109 move_assignment &operator=(const move_assignment &) = default; \
1113 MPARK_VARIANT_MOVE_ASSIGNMENT(
1114 Trait::TriviallyAvailable
,
1115 move_assignment
&operator=(move_assignment
&&that
) = default;);
1117 MPARK_VARIANT_MOVE_ASSIGNMENT(
1120 operator=(move_assignment
&&that
) noexcept(
1121 lib::all
<(std::is_nothrow_move_constructible
<Ts
>::value
&&
1122 std::is_nothrow_move_assignable
<Ts
>::value
)...>::value
) {
1123 this->generic_assign(lib::move(that
));
1127 MPARK_VARIANT_MOVE_ASSIGNMENT(
1129 move_assignment
&operator=(move_assignment
&&) = delete;);
1131 #undef MPARK_VARIANT_MOVE_ASSIGNMENT
1133 template <typename Traits
, Trait
= Traits::copy_assignable_trait
>
1134 class copy_assignment
;
1136 #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
1137 template <typename... Ts> \
1138 class copy_assignment<traits<Ts...>, copy_assignable_trait> \
1139 : public move_assignment<traits<Ts...>> { \
1140 using super = move_assignment<traits<Ts...>>; \
1143 INHERITING_CTOR(copy_assignment, super) \
1144 using super::operator=; \
1146 copy_assignment(const copy_assignment &) = default; \
1147 copy_assignment(copy_assignment &&) = default; \
1148 ~copy_assignment() = default; \
1150 copy_assignment &operator=(copy_assignment &&) = default; \
1153 MPARK_VARIANT_COPY_ASSIGNMENT(
1154 Trait::TriviallyAvailable
,
1155 copy_assignment
&operator=(const copy_assignment
&that
) = default;);
1157 MPARK_VARIANT_COPY_ASSIGNMENT(
1159 copy_assignment
&operator=(const copy_assignment
&that
) {
1160 this->generic_assign(that
);
1164 MPARK_VARIANT_COPY_ASSIGNMENT(
1166 copy_assignment
&operator=(const copy_assignment
&) = delete;);
1168 #undef MPARK_VARIANT_COPY_ASSIGNMENT
1170 template <typename
... Ts
>
1171 class impl
: public copy_assignment
<traits
<Ts
...>> {
1172 using super
= copy_assignment
<traits
<Ts
...>>;
1175 INHERITING_CTOR(impl
, super
)
1176 using super::operator=;
1178 template <std::size_t I
, typename Arg
>
1179 inline void assign(Arg
&&arg
) {
1180 this->assign_alt(access::base::get_alt
<I
>(*this),
1181 lib::forward
<Arg
>(arg
));
1184 inline void swap(impl
&that
) {
1185 if (this->valueless_by_exception() && that
.valueless_by_exception()) {
1187 } else if (this->index() == that
.index()) {
1188 visitation::base::visit_alt_at(this->index(),
1189 #ifdef MPARK_GENERIC_LAMBDAS
1190 [](auto &this_alt
, auto &that_alt
) {
1192 swap(this_alt
.value
,
1203 impl
*rhs
= lib::addressof(that
);
1204 if (lhs
->move_nothrow() && !rhs
->move_nothrow()) {
1205 std::swap(lhs
, rhs
);
1207 impl
tmp(lib::move(*rhs
));
1208 #ifdef MPARK_EXCEPTIONS
1209 // EXTENSION: When the move construction of `lhs` into `rhs` throws
1210 // and `tmp` is nothrow move constructible then we move `tmp` back
1211 // into `rhs` and provide the strong exception safety guarantee.
1213 this->generic_construct(*rhs
, lib::move(*lhs
));
1215 if (tmp
.move_nothrow()) {
1216 this->generic_construct(*rhs
, lib::move(tmp
));
1221 this->generic_construct(*rhs
, lib::move(*lhs
));
1223 this->generic_construct(*lhs
, lib::move(tmp
));
1228 #ifndef MPARK_GENERIC_LAMBDAS
1230 template <typename ThisAlt
, typename ThatAlt
>
1231 inline void operator()(ThisAlt
&this_alt
, ThatAlt
&that_alt
) const {
1233 swap(this_alt
.value
, that_alt
.value
);
1238 inline constexpr bool move_nothrow() const {
1239 return this->valueless_by_exception() ||
1240 lib::array
<bool, sizeof...(Ts
)>{
1241 {std::is_nothrow_move_constructible
<Ts
>::value
...}
1246 template <std::size_t I
, typename T
>
1247 struct overload_leaf
{
1248 using F
= lib::size_constant
<I
> (*)(T
);
1249 operator F() const { return nullptr; }
1252 template <typename
... Ts
>
1253 struct overload_impl
{
1258 template <std::size_t... Is
>
1259 struct impl
<lib::index_sequence
<Is
...>> : overload_leaf
<Is
, Ts
>... {};
1262 using type
= impl
<lib::index_sequence_for
<Ts
...>>;
1265 template <typename
... Ts
>
1266 using overload
= typename overload_impl
<Ts
...>::type
;
1268 template <typename T
, typename
... Ts
>
1269 using best_match
= lib::invoke_result_t
<overload
<Ts
...>, T
&&>;
1271 template <typename T
>
1272 struct is_in_place_index
: std::false_type
{};
1274 template <std::size_t I
>
1275 struct is_in_place_index
<in_place_index_t
<I
>> : std::true_type
{};
1277 template <typename T
>
1278 struct is_in_place_type
: std::false_type
{};
1280 template <typename T
>
1281 struct is_in_place_type
<in_place_type_t
<T
>> : std::true_type
{};
1285 template <typename
... Ts
>
1287 static_assert(0 < sizeof...(Ts
),
1288 "variant must consist of at least one alternative.");
1290 static_assert(lib::all
<!std::is_array
<Ts
>::value
...>::value
,
1291 "variant can not have an array type as an alternative.");
1293 static_assert(lib::all
<!std::is_reference
<Ts
>::value
...>::value
,
1294 "variant can not have a reference type as an alternative.");
1296 static_assert(lib::all
<!std::is_void
<Ts
>::value
...>::value
,
1297 "variant can not have a void type as an alternative.");
1301 typename Front
= lib::type_pack_element_t
<0, Ts
...>,
1302 lib::enable_if_t
<std::is_default_constructible
<Front
>::value
, int> = 0>
1303 inline constexpr variant() noexcept(
1304 std::is_nothrow_default_constructible
<Front
>::value
)
1305 : impl_(in_place_index_t
<0>{}) {}
1307 variant(const variant
&) = default;
1308 variant(variant
&&) = default;
1312 typename Decayed
= lib::decay_t
<Arg
>,
1313 lib::enable_if_t
<!std::is_same
<Decayed
, variant
>::value
, int> = 0,
1314 lib::enable_if_t
<!detail::is_in_place_index
<Decayed
>::value
, int> = 0,
1315 lib::enable_if_t
<!detail::is_in_place_type
<Decayed
>::value
, int> = 0,
1316 std::size_t I
= detail::best_match
<Arg
, Ts
...>::value
,
1317 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1318 lib::enable_if_t
<std::is_constructible
<T
, Arg
>::value
, int> = 0>
1319 inline constexpr variant(Arg
&&arg
) noexcept(
1320 std::is_nothrow_constructible
<T
, Arg
>::value
)
1321 : impl_(in_place_index_t
<I
>{}, lib::forward
<Arg
>(arg
)) {}
1326 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1327 lib::enable_if_t
<std::is_constructible
<T
, Args
...>::value
, int> = 0>
1328 inline explicit constexpr variant(
1329 in_place_index_t
<I
>,
1330 Args
&&... args
) noexcept(std::is_nothrow_constructible
<T
,
1332 : impl_(in_place_index_t
<I
>{}, lib::forward
<Args
>(args
)...) {}
1338 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1339 lib::enable_if_t
<std::is_constructible
<T
,
1340 std::initializer_list
<Up
> &,
1343 inline explicit constexpr variant(
1344 in_place_index_t
<I
>,
1345 std::initializer_list
<Up
> il
,
1346 Args
&&... args
) noexcept(std::
1347 is_nothrow_constructible
<
1349 std::initializer_list
<Up
> &,
1351 : impl_(in_place_index_t
<I
>{}, il
, lib::forward
<Args
>(args
)...) {}
1356 std::size_t I
= detail::find_index_sfinae
<T
, Ts
...>::value
,
1357 lib::enable_if_t
<std::is_constructible
<T
, Args
...>::value
, int> = 0>
1358 inline explicit constexpr variant(
1360 Args
&&... args
) noexcept(std::is_nothrow_constructible
<T
,
1362 : impl_(in_place_index_t
<I
>{}, lib::forward
<Args
>(args
)...) {}
1368 std::size_t I
= detail::find_index_sfinae
<T
, Ts
...>::value
,
1369 lib::enable_if_t
<std::is_constructible
<T
,
1370 std::initializer_list
<Up
> &,
1373 inline explicit constexpr variant(
1375 std::initializer_list
<Up
> il
,
1376 Args
&&... args
) noexcept(std::
1377 is_nothrow_constructible
<
1379 std::initializer_list
<Up
> &,
1381 : impl_(in_place_index_t
<I
>{}, il
, lib::forward
<Args
>(args
)...) {}
1383 ~variant() = default;
1385 variant
&operator=(const variant
&) = default;
1386 variant
&operator=(variant
&&) = default;
1388 template <typename Arg
,
1389 lib::enable_if_t
<!std::is_same
<lib::decay_t
<Arg
>, variant
>::value
,
1391 std::size_t I
= detail::best_match
<Arg
, Ts
...>::value
,
1392 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1393 lib::enable_if_t
<(std::is_assignable
<T
&, Arg
>::value
&&
1394 std::is_constructible
<T
, Arg
>::value
),
1396 inline variant
&operator=(Arg
&&arg
) noexcept(
1397 (std::is_nothrow_assignable
<T
&, Arg
>::value
&&
1398 std::is_nothrow_constructible
<T
, Arg
>::value
)) {
1399 impl_
.template assign
<I
>(lib::forward
<Arg
>(arg
));
1406 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1407 lib::enable_if_t
<std::is_constructible
<T
, Args
...>::value
, int> = 0>
1408 inline T
&emplace(Args
&&... args
) {
1409 return impl_
.template emplace
<I
>(lib::forward
<Args
>(args
)...);
1416 typename T
= lib::type_pack_element_t
<I
, Ts
...>,
1417 lib::enable_if_t
<std::is_constructible
<T
,
1418 std::initializer_list
<Up
> &,
1421 inline T
&emplace(std::initializer_list
<Up
> il
, Args
&&... args
) {
1422 return impl_
.template emplace
<I
>(il
, lib::forward
<Args
>(args
)...);
1428 std::size_t I
= detail::find_index_sfinae
<T
, Ts
...>::value
,
1429 lib::enable_if_t
<std::is_constructible
<T
, Args
...>::value
, int> = 0>
1430 inline T
&emplace(Args
&&... args
) {
1431 return impl_
.template emplace
<I
>(lib::forward
<Args
>(args
)...);
1438 std::size_t I
= detail::find_index_sfinae
<T
, Ts
...>::value
,
1439 lib::enable_if_t
<std::is_constructible
<T
,
1440 std::initializer_list
<Up
> &,
1443 inline T
&emplace(std::initializer_list
<Up
> il
, Args
&&... args
) {
1444 return impl_
.template emplace
<I
>(il
, lib::forward
<Args
>(args
)...);
1447 inline constexpr bool valueless_by_exception() const noexcept
{
1448 return impl_
.valueless_by_exception();
1451 inline constexpr std::size_t index() const noexcept
{
1452 return impl_
.index();
1457 lib::enable_if_t
<lib::all
<Dummy
,
1458 (std::is_move_constructible
<Ts
>::value
&&
1459 lib::is_swappable
<Ts
>::value
)...>::value
,
1461 inline void swap(variant
&that
) noexcept(
1462 lib::all
<(std::is_nothrow_move_constructible
<Ts
>::value
&&
1463 lib::is_nothrow_swappable
<Ts
>::value
)...>::value
) {
1464 impl_
.swap(that
.impl_
);
1468 detail::impl
<Ts
...> impl_
;
1470 friend struct detail::access::variant
;
1471 friend struct detail::visitation::variant
;
1474 template <std::size_t I
, typename
... Ts
>
1475 inline constexpr bool holds_alternative(const variant
<Ts
...> &v
) noexcept
{
1476 return v
.index() == I
;
1479 template <typename T
, typename
... Ts
>
1480 inline constexpr bool holds_alternative(const variant
<Ts
...> &v
) noexcept
{
1481 return holds_alternative
<detail::find_index_checked
<T
, Ts
...>::value
>(v
);
1485 template <std::size_t I
, typename V
>
1486 struct generic_get_impl
{
1487 constexpr generic_get_impl(int) {}
1489 constexpr AUTO_REFREF
operator()(V
&&v
) const
1491 access::variant::get_alt
<I
>(lib::forward
<V
>(v
)).value
)
1494 template <std::size_t I
, typename V
>
1495 inline constexpr AUTO_REFREF
generic_get(V
&&v
)
1496 AUTO_REFREF_RETURN(generic_get_impl
<I
, V
>(
1497 holds_alternative
<I
>(v
) ? 0 : (throw_bad_variant_access(), 0))(
1498 lib::forward
<V
>(v
)))
1499 } // namespace detail
1501 template <std::size_t I
, typename
... Ts
>
1502 inline constexpr variant_alternative_t
<I
, variant
<Ts
...>> &get(
1503 variant
<Ts
...> &v
) {
1504 return detail::generic_get
<I
>(v
);
1507 template <std::size_t I
, typename
... Ts
>
1508 inline constexpr variant_alternative_t
<I
, variant
<Ts
...>> &&get(
1509 variant
<Ts
...> &&v
) {
1510 return detail::generic_get
<I
>(lib::move(v
));
1513 template <std::size_t I
, typename
... Ts
>
1514 inline constexpr const variant_alternative_t
<I
, variant
<Ts
...>> &get(
1515 const variant
<Ts
...> &v
) {
1516 return detail::generic_get
<I
>(v
);
1519 template <std::size_t I
, typename
... Ts
>
1520 inline constexpr const variant_alternative_t
<I
, variant
<Ts
...>> &&get(
1521 const variant
<Ts
...> &&v
) {
1522 return detail::generic_get
<I
>(lib::move(v
));
1525 template <typename T
, typename
... Ts
>
1526 inline constexpr T
&get(variant
<Ts
...> &v
) {
1527 return get
<detail::find_index_checked
<T
, Ts
...>::value
>(v
);
1530 template <typename T
, typename
... Ts
>
1531 inline constexpr T
&&get(variant
<Ts
...> &&v
) {
1532 return get
<detail::find_index_checked
<T
, Ts
...>::value
>(lib::move(v
));
1535 template <typename T
, typename
... Ts
>
1536 inline constexpr const T
&get(const variant
<Ts
...> &v
) {
1537 return get
<detail::find_index_checked
<T
, Ts
...>::value
>(v
);
1540 template <typename T
, typename
... Ts
>
1541 inline constexpr const T
&&get(const variant
<Ts
...> &&v
) {
1542 return get
<detail::find_index_checked
<T
, Ts
...>::value
>(lib::move(v
));
1547 template <std::size_t I
, typename V
>
1548 inline constexpr /* auto * */ AUTO
generic_get_if(V
*v
) noexcept
1549 AUTO_RETURN(v
&& holds_alternative
<I
>(*v
)
1550 ? lib::addressof(access::variant::get_alt
<I
>(*v
).value
)
1553 } // namespace detail
1555 template <std::size_t I
, typename
... Ts
>
1556 inline constexpr lib::add_pointer_t
<variant_alternative_t
<I
, variant
<Ts
...>>>
1557 get_if(variant
<Ts
...> *v
) noexcept
{
1558 return detail::generic_get_if
<I
>(v
);
1561 template <std::size_t I
, typename
... Ts
>
1562 inline constexpr lib::add_pointer_t
<
1563 const variant_alternative_t
<I
, variant
<Ts
...>>>
1564 get_if(const variant
<Ts
...> *v
) noexcept
{
1565 return detail::generic_get_if
<I
>(v
);
1568 template <typename T
, typename
... Ts
>
1569 inline constexpr lib::add_pointer_t
<T
>
1570 get_if(variant
<Ts
...> *v
) noexcept
{
1571 return get_if
<detail::find_index_checked
<T
, Ts
...>::value
>(v
);
1574 template <typename T
, typename
... Ts
>
1575 inline constexpr lib::add_pointer_t
<const T
>
1576 get_if(const variant
<Ts
...> *v
) noexcept
{
1577 return get_if
<detail::find_index_checked
<T
, Ts
...>::value
>(v
);
1580 template <typename
... Ts
>
1581 inline constexpr bool operator==(const variant
<Ts
...> &lhs
,
1582 const variant
<Ts
...> &rhs
) {
1583 using detail::visitation::variant
;
1584 using lib::equal_to
;
1585 #ifdef MPARK_CPP14_CONSTEXPR
1586 if (lhs
.index() != rhs
.index()) return false;
1587 if (lhs
.valueless_by_exception()) return true;
1588 return variant::visit_value_at(lhs
.index(), equal_to
{}, lhs
, rhs
);
1590 return lhs
.index() == rhs
.index() &&
1591 (lhs
.valueless_by_exception() ||
1592 variant::visit_value_at(lhs
.index(), equal_to
{}, lhs
, rhs
));
1596 template <typename
... Ts
>
1597 inline constexpr bool operator!=(const variant
<Ts
...> &lhs
,
1598 const variant
<Ts
...> &rhs
) {
1599 using detail::visitation::variant
;
1600 using lib::not_equal_to
;
1601 #ifdef MPARK_CPP14_CONSTEXPR
1602 if (lhs
.index() != rhs
.index()) return true;
1603 if (lhs
.valueless_by_exception()) return false;
1604 return variant::visit_value_at(lhs
.index(), not_equal_to
{}, lhs
, rhs
);
1606 return lhs
.index() != rhs
.index() ||
1607 (!lhs
.valueless_by_exception() &&
1608 variant::visit_value_at(lhs
.index(), not_equal_to
{}, lhs
, rhs
));
1612 template <typename
... Ts
>
1613 inline constexpr bool operator<(const variant
<Ts
...> &lhs
,
1614 const variant
<Ts
...> &rhs
) {
1615 using detail::visitation::variant
;
1617 #ifdef MPARK_CPP14_CONSTEXPR
1618 if (rhs
.valueless_by_exception()) return false;
1619 if (lhs
.valueless_by_exception()) return true;
1620 if (lhs
.index() < rhs
.index()) return true;
1621 if (lhs
.index() > rhs
.index()) return false;
1622 return variant::visit_value_at(lhs
.index(), less
{}, lhs
, rhs
);
1624 return !rhs
.valueless_by_exception() &&
1625 (lhs
.valueless_by_exception() || lhs
.index() < rhs
.index() ||
1626 (lhs
.index() == rhs
.index() &&
1627 variant::visit_value_at(lhs
.index(), less
{}, lhs
, rhs
)));
1631 template <typename
... Ts
>
1632 inline constexpr bool operator>(const variant
<Ts
...> &lhs
,
1633 const variant
<Ts
...> &rhs
) {
1634 using detail::visitation::variant
;
1636 #ifdef MPARK_CPP14_CONSTEXPR
1637 if (lhs
.valueless_by_exception()) return false;
1638 if (rhs
.valueless_by_exception()) return true;
1639 if (lhs
.index() > rhs
.index()) return true;
1640 if (lhs
.index() < rhs
.index()) return false;
1641 return variant::visit_value_at(lhs
.index(), greater
{}, lhs
, rhs
);
1643 return !lhs
.valueless_by_exception() &&
1644 (rhs
.valueless_by_exception() || lhs
.index() > rhs
.index() ||
1645 (lhs
.index() == rhs
.index() &&
1646 variant::visit_value_at(lhs
.index(), greater
{}, lhs
, rhs
)));
1650 template <typename
... Ts
>
1651 inline constexpr bool operator<=(const variant
<Ts
...> &lhs
,
1652 const variant
<Ts
...> &rhs
) {
1653 using detail::visitation::variant
;
1654 using lib::less_equal
;
1655 #ifdef MPARK_CPP14_CONSTEXPR
1656 if (lhs
.valueless_by_exception()) return true;
1657 if (rhs
.valueless_by_exception()) return false;
1658 if (lhs
.index() < rhs
.index()) return true;
1659 if (lhs
.index() > rhs
.index()) return false;
1660 return variant::visit_value_at(lhs
.index(), less_equal
{}, lhs
, rhs
);
1662 return lhs
.valueless_by_exception() ||
1663 (!rhs
.valueless_by_exception() &&
1664 (lhs
.index() < rhs
.index() ||
1665 (lhs
.index() == rhs
.index() &&
1666 variant::visit_value_at(lhs
.index(), less_equal
{}, lhs
, rhs
))));
1670 template <typename
... Ts
>
1671 inline constexpr bool operator>=(const variant
<Ts
...> &lhs
,
1672 const variant
<Ts
...> &rhs
) {
1673 using detail::visitation::variant
;
1674 using lib::greater_equal
;
1675 #ifdef MPARK_CPP14_CONSTEXPR
1676 if (rhs
.valueless_by_exception()) return true;
1677 if (lhs
.valueless_by_exception()) return false;
1678 if (lhs
.index() > rhs
.index()) return true;
1679 if (lhs
.index() < rhs
.index()) return false;
1680 return variant::visit_value_at(lhs
.index(), greater_equal
{}, lhs
, rhs
);
1682 return rhs
.valueless_by_exception() ||
1683 (!lhs
.valueless_by_exception() &&
1684 (lhs
.index() > rhs
.index() ||
1685 (lhs
.index() == rhs
.index() &&
1686 variant::visit_value_at(
1687 lhs
.index(), greater_equal
{}, lhs
, rhs
))));
1691 struct monostate
{};
1693 inline constexpr bool operator<(monostate
, monostate
) noexcept
{
1697 inline constexpr bool operator>(monostate
, monostate
) noexcept
{
1701 inline constexpr bool operator<=(monostate
, monostate
) noexcept
{
1705 inline constexpr bool operator>=(monostate
, monostate
) noexcept
{
1709 inline constexpr bool operator==(monostate
, monostate
) noexcept
{
1713 inline constexpr bool operator!=(monostate
, monostate
) noexcept
{
1717 #ifdef MPARK_CPP14_CONSTEXPR
1720 inline constexpr bool all(std::initializer_list
<bool> bs
) {
1729 } // namespace detail
1731 template <typename Visitor
, typename
... Vs
>
1732 inline constexpr decltype(auto) visit(Visitor
&&visitor
, Vs
&&... vs
) {
1733 return (detail::all({!vs
.valueless_by_exception()...})
1735 : throw_bad_variant_access()),
1736 detail::visitation::variant::visit_value(
1737 lib::forward
<Visitor
>(visitor
), lib::forward
<Vs
>(vs
)...);
1742 template <std::size_t N
>
1743 inline constexpr bool all_impl(const lib::array
<bool, N
> &bs
,
1745 return idx
>= N
|| (bs
[idx
] && all_impl(bs
, idx
+ 1));
1748 template <std::size_t N
>
1749 inline constexpr bool all(const lib::array
<bool, N
> &bs
) {
1750 return all_impl(bs
, 0);
1753 } // namespace detail
1755 template <typename Visitor
, typename
... Vs
>
1756 inline constexpr DECLTYPE_AUTO
visit(Visitor
&&visitor
, Vs
&&... vs
)
1757 DECLTYPE_AUTO_RETURN(
1759 lib::array
<bool, sizeof...(Vs
)>{{!vs
.valueless_by_exception()...}})
1761 : throw_bad_variant_access()),
1762 detail::visitation::variant::visit_value(lib::forward
<Visitor
>(visitor
),
1763 lib::forward
<Vs
>(vs
)...))
1766 template <typename
... Ts
>
1767 inline auto swap(variant
<Ts
...> &lhs
,
1768 variant
<Ts
...> &rhs
) noexcept(noexcept(lhs
.swap(rhs
)))
1769 -> decltype(lhs
.swap(rhs
)) {
1775 template <typename T
, typename
...>
1776 using enabled_type
= T
;
1780 template <typename H
, typename K
>
1781 constexpr bool meets_requirements() {
1782 return std::is_copy_constructible
<H
>::value
&&
1783 std::is_move_constructible
<H
>::value
&&
1784 lib::is_invocable_r
<std::size_t, H
, const K
&>::value
;
1787 template <typename K
>
1788 constexpr bool is_enabled() {
1789 using H
= std::hash
<K
>;
1790 return meets_requirements
<H
, K
>() &&
1791 std::is_default_constructible
<H
>::value
&&
1792 std::is_copy_assignable
<H
>::value
&&
1793 std::is_move_assignable
<H
>::value
;
1798 } // namespace detail
1804 #undef AUTO_REFREF_RETURN
1806 #undef DECLTYPE_AUTO
1807 #undef DECLTYPE_AUTO_RETURN
1809 } // namespace mpark
1813 template <typename
... Ts
>
1814 struct hash
<mpark::detail::enabled_type
<
1815 mpark::variant
<Ts
...>,
1816 mpark::lib::enable_if_t
<mpark::lib::all
<mpark::detail::hash::is_enabled
<
1817 mpark::lib::remove_const_t
<Ts
>>()...>::value
>>> {
1818 using argument_type
= mpark::variant
<Ts
...>;
1819 using result_type
= std::size_t;
1821 inline result_type
operator()(const argument_type
&v
) const {
1822 using mpark::detail::visitation::variant
;
1823 std::size_t result
=
1824 v
.valueless_by_exception()
1825 ? 299792458 // Random value chosen by the universe upon creation
1826 : variant::visit_alt(
1827 #ifdef MPARK_GENERIC_LAMBDAS
1828 [](const auto &alt
) {
1829 using alt_type
= mpark::lib::decay_t
<decltype(alt
)>;
1830 using value_type
= mpark::lib::remove_const_t
<
1831 typename
alt_type::value_type
>;
1832 return hash
<value_type
>{}(alt
.value
);
1839 return hash_combine(result
, hash
<std::size_t>{}(v
.index()));
1843 #ifndef MPARK_GENERIC_LAMBDAS
1845 template <typename Alt
>
1846 inline std::size_t operator()(const Alt
&alt
) const {
1847 using alt_type
= mpark::lib::decay_t
<Alt
>;
1849 mpark::lib::remove_const_t
<typename
alt_type::value_type
>;
1850 return hash
<value_type
>{}(alt
.value
);
1855 static std::size_t hash_combine(std::size_t lhs
, std::size_t rhs
) {
1856 return lhs
^= rhs
+ 0x9e3779b9 + (lhs
<< 6) + (lhs
>> 2);
1861 struct hash
<mpark::monostate
> {
1862 using argument_type
= mpark::monostate
;
1863 using result_type
= std::size_t;
1865 inline result_type
operator()(const argument_type
&) const noexcept
{
1866 return 66740831; // return a fundamentally attractive random value.
1872 #endif // MPARK_VARIANT_HPP