Use rvalue or const lvalue references for some parameters
[alure.git] / include / mpark / variant.hpp
blob8f9c17c6ae2de2a24b4146b520621fe6e077f6b8
1 // MPark.Variant
2 //
3 // Copyright Michael Park, 2015-2017
4 //
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
12 variant synopsis
14 namespace std {
16 // 20.7.2, class template variant
17 template <class... Types>
18 class variant {
19 public:
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
43 ~variant();
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;
68 // 20.7.2.6, swap
69 void swap(variant&) noexcept(see below);
72 // 20.7.3, variant helper classes
73 template <class T> struct variant_size; // undefined
75 template <class T>
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
171 struct 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>;
193 } // namespace std
197 #include <cstddef>
198 #include <exception>
199 #include <functional>
200 #include <initializer_list>
201 #include <new>
202 #include <type_traits>
203 #include <utility>
205 #include "config.hpp"
206 #include "in_place.hpp"
207 #include "lib.hpp"
209 namespace mpark {
211 #ifdef MPARK_RETURN_TYPE_DEDUCTION
213 #define AUTO auto
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__; }
222 #else
224 #define AUTO auto
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__; }
239 #endif
241 class bad_variant_access : public std::exception {
242 public:
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{};
249 #else
250 std::terminate();
251 #ifdef MPARK_BUILTIN_UNREACHABLE
252 __builtin_unreachable();
253 #endif
254 #endif
257 template <typename... Ts>
258 class variant;
260 template <typename T>
261 struct variant_size;
263 #ifdef MPARK_VARIABLE_TEMPLATES
264 template <typename T>
265 constexpr std::size_t variant_size_v = variant_size<T>::value;
266 #endif
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);
307 namespace detail {
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) {
320 if (matches[i]) {
321 if (result != not_found) {
322 return ambiguous;
324 result = i;
327 return result;
329 #else
330 inline constexpr std::size_t find_index_impl(std::size_t result,
331 std::size_t) {
332 return result;
335 template <typename... Bs>
336 inline constexpr std::size_t find_index_impl(std::size_t result,
337 std::size_t idx,
338 bool b,
339 Bs... bs) {
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...);
349 #endif
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)) {
388 result = t;
391 return result;
393 #else
394 inline constexpr Trait common_trait_impl(Trait result) { return result; }
396 template <typename... Traits>
397 inline constexpr Trait common_trait_impl(Trait result,
398 Trait t,
399 Traits... ts) {
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...);
409 #endif
411 template <typename... Ts>
412 struct traits {
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,
425 trait<Ts,
426 lib::is_trivially_copy_assignable,
427 std::is_copy_assignable>()...);
429 static constexpr Trait move_assignable_trait =
430 common_trait(move_constructible_trait,
431 trait<Ts,
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>()...);
441 namespace access {
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>{});
454 #else
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)))
472 #endif
475 struct base {
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>{}))
482 struct variant {
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 {
492 struct base {
493 private:
494 template <typename T>
495 inline static constexpr const T &at(const T &elem) {
496 return 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 "
509 "return type.");
510 return 0;
513 template <typename... Fs>
514 inline static constexpr lib::array<
515 lib::common_type_t<lib::decay_t<Fs>...>,
516 sizeof...(Fs)>
517 make_farray(Fs &&... fs) {
518 using result = lib::array<lib::common_type_t<lib::decay_t<Fs>...>,
519 sizeof...(Fs)>;
520 return visit_visitor_return_type_check<lib::decay_t<Fs>...>(),
521 result{{lib::forward<Fs>(fs)...}};
524 template <std::size_t... Is>
525 struct dispatcher {
526 template <typename F, typename... Vs>
527 struct impl {
528 inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
529 DECLTYPE_AUTO_RETURN(lib::invoke(
530 static_cast<F>(f),
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,
568 typename... Vs,
569 std::size_t... Is,
570 std::size_t... Js,
571 typename... Ls>
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()>{}...);
584 #else
585 template <typename F, typename... Vs>
586 struct make_fmatrix_impl {
587 template <typename...>
588 struct impl;
590 template <std::size_t... Is>
591 struct impl<lib::index_sequence<Is...>> {
592 inline constexpr AUTO operator()() const
593 AUTO_RETURN(
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...>,
600 Ls...> {
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()
609 AUTO_RETURN(
610 typename make_fmatrix_impl<F, Vs...>::template impl<
611 lib::index_sequence<>,
612 lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
613 #endif
615 public:
616 template <typename Visitor, typename... Vs>
617 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
618 Visitor &&visitor,
619 Vs &&... vs)
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,
628 Vs &&... vs)
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))...))
636 struct variant {
637 private:
638 template <typename Visitor, typename... Values>
639 struct visit_exhaustive_visitor_check {
640 static_assert(
641 lib::is_invocable<Visitor, Values...>::value,
642 "`mpark::visit` requires the visitor to be exhaustive.");
644 #ifdef _MSC_VER
645 #pragma warning(push)
646 #pragma warning(disable : 4100)
647 #endif
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)...))
652 #ifdef _MSC_VER
653 #pragma warning(pop)
654 #endif
657 template <typename Visitor>
658 struct value_visitor {
659 Visitor &&visitor_;
661 template <typename... Alts>
662 inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const
663 DECLTYPE_AUTO_RETURN(
664 visit_exhaustive_visitor_check<
665 Visitor,
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)})
675 public:
676 template <typename Visitor, typename... Vs>
677 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
678 Visitor &&visitor,
679 Vs &&... vs)
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,
687 Vs &&... vs)
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,
693 Visitor &&visitor,
694 Vs &&... vs)
695 DECLTYPE_AUTO_RETURN(
696 visit_alt_at(index,
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,
702 Vs &&... vs)
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>
711 struct alt {
712 using value_type = T;
714 #ifdef _MSC_VER
715 #pragma warning(push)
716 #pragma warning(disable : 4244)
717 #endif
718 template <typename... Args>
719 inline explicit constexpr alt(in_place_t, Args &&... args)
720 : value(lib::forward<Args>(args)...) {}
721 #ifdef _MSC_VER
722 #pragma warning(pop)
723 #endif
725 T value;
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...> { \
737 public: \
738 inline explicit constexpr recursive_union(valueless_t) noexcept \
739 : dummy_{} {} \
741 template <typename... Args> \
742 inline explicit constexpr recursive_union(in_place_index_t<0>, \
743 Args &&... args) \
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>, \
748 Args &&... args) \
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; \
754 destructor \
756 recursive_union &operator=(const recursive_union &) = default; \
757 recursive_union &operator=(recursive_union &&) = default; \
759 private: \
760 char dummy_; \
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>
779 class base {
780 public:
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)...),
787 index_(I) {}
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_;
797 protected:
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); }
812 data_t data_;
813 index_t index_;
815 friend struct access::base;
816 friend struct visitation::base;
819 struct dtor {
820 #ifdef _MSC_VER
821 #pragma warning(push)
822 #pragma warning(disable : 4100)
823 #endif
824 template <typename Alt>
825 inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }
826 #ifdef _MSC_VER
827 #pragma warning(pop)
828 #endif
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)...) {}
836 #else
837 #define INHERITING_CTOR(type, base) using base::base;
838 #endif
840 template <typename Traits, Trait = Traits::destructible_trait>
841 class destructor;
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...>; \
849 public: \
850 INHERITING_CTOR(destructor, super) \
851 using super::operator=; \
853 destructor(const destructor &) = default; \
854 destructor(destructor &&) = default; \
855 definition \
856 destructor &operator=(const destructor &) = default; \
857 destructor &operator=(destructor &&) = default; \
859 protected: \
860 destroy \
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(
871 Trait::Available,
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(
881 Trait::Unavailable,
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>;
891 public:
892 INHERITING_CTOR(constructor, super)
893 using super::operator=;
895 protected:
896 #ifndef MPARK_GENERIC_LAMBDAS
897 struct ctor {
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);
904 #endif
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)...);
910 return a.value;
913 template <typename Rhs>
914 inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
915 lhs.destroy();
916 if (!rhs.valueless_by_exception()) {
917 visitation::base::visit_alt_at(
918 rhs.index(),
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);
924 #else
925 ctor{}
926 #endif
928 lhs,
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...>>; \
944 public: \
945 INHERITING_CTOR(move_constructor, super) \
946 using super::operator=; \
948 move_constructor(const move_constructor &) = default; \
949 definition \
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(
960 Trait::Available,
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(
968 Trait::Unavailable,
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...>>; \
982 public: \
983 INHERITING_CTOR(copy_constructor, super) \
984 using super::operator=; \
986 definition \
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(
998 Trait::Available,
999 copy_constructor(const copy_constructor &that)
1000 : copy_constructor(valueless_t{}) {
1001 this->generic_construct(*this, that);
1004 MPARK_VARIANT_COPY_CONSTRUCTOR(
1005 Trait::Unavailable,
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>;
1014 public:
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)...)) {
1022 this->destroy();
1023 auto &result = this->construct_alt(access::base::get_alt<I>(*this),
1024 lib::forward<Args>(args)...);
1025 this->index_ = I;
1026 return result;
1029 protected:
1030 #ifndef MPARK_GENERIC_LAMBDAS
1031 template <typename That>
1032 struct assigner {
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);
1037 assignment *self;
1039 #endif
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) {
1044 #ifdef _MSC_VER
1045 #pragma warning(push)
1046 #pragma warning(disable : 4244)
1047 #endif
1048 a.value = lib::forward<Arg>(arg);
1049 #ifdef _MSC_VER
1050 #pragma warning(pop)
1051 #endif
1052 } else {
1053 struct {
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_)));
1060 assignment *this_;
1061 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()) {
1072 // do nothing.
1073 } else if (that.valueless_by_exception()) {
1074 this->destroy();
1075 } else {
1076 visitation::base::visit_alt_at(
1077 that.index(),
1078 #ifdef MPARK_GENERIC_LAMBDAS
1079 [this](auto &this_alt, auto &&that_alt) {
1080 this->assign_alt(
1081 this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
1083 #else
1084 assigner<That>{this}
1085 #endif
1087 *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...>>; \
1102 public: \
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; \
1110 definition \
1113 MPARK_VARIANT_MOVE_ASSIGNMENT(
1114 Trait::TriviallyAvailable,
1115 move_assignment &operator=(move_assignment &&that) = default;);
1117 MPARK_VARIANT_MOVE_ASSIGNMENT(
1118 Trait::Available,
1119 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));
1124 return *this;
1127 MPARK_VARIANT_MOVE_ASSIGNMENT(
1128 Trait::Unavailable,
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...>>; \
1142 public: \
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; \
1149 definition \
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(
1158 Trait::Available,
1159 copy_assignment &operator=(const copy_assignment &that) {
1160 this->generic_assign(that);
1161 return *this;
1164 MPARK_VARIANT_COPY_ASSIGNMENT(
1165 Trait::Unavailable,
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...>>;
1174 public:
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()) {
1186 // do nothing.
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) {
1191 using std::swap;
1192 swap(this_alt.value,
1193 that_alt.value);
1195 #else
1196 swapper{}
1197 #endif
1199 *this,
1200 that);
1201 } else {
1202 impl *lhs = this;
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.
1212 try {
1213 this->generic_construct(*rhs, lib::move(*lhs));
1214 } catch (...) {
1215 if (tmp.move_nothrow()) {
1216 this->generic_construct(*rhs, lib::move(tmp));
1218 throw;
1220 #else
1221 this->generic_construct(*rhs, lib::move(*lhs));
1222 #endif
1223 this->generic_construct(*lhs, lib::move(tmp));
1227 private:
1228 #ifndef MPARK_GENERIC_LAMBDAS
1229 struct swapper {
1230 template <typename ThisAlt, typename ThatAlt>
1231 inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const {
1232 using std::swap;
1233 swap(this_alt.value, that_alt.value);
1236 #endif
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...}
1242 }[this->index()];
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 {
1254 private:
1255 template <typename>
1256 struct impl;
1258 template <std::size_t... Is>
1259 struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {};
1261 public:
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 {};
1283 } // detail
1285 template <typename... Ts>
1286 class variant {
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.");
1299 public:
1300 template <
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;
1310 template <
1311 typename Arg,
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)) {}
1323 template <
1324 std::size_t I,
1325 typename... Args,
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,
1331 Args...>::value)
1332 : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
1334 template <
1335 std::size_t I,
1336 typename Up,
1337 typename... 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> &,
1341 Args...>::value,
1342 int> = 0>
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> &,
1350 Args...>::value)
1351 : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
1353 template <
1354 typename T,
1355 typename... 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(
1359 in_place_type_t<T>,
1360 Args &&... args) noexcept(std::is_nothrow_constructible<T,
1361 Args...>::value)
1362 : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
1364 template <
1365 typename T,
1366 typename Up,
1367 typename... 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> &,
1371 Args...>::value,
1372 int> = 0>
1373 inline explicit constexpr variant(
1374 in_place_type_t<T>,
1375 std::initializer_list<Up> il,
1376 Args &&... args) noexcept(std::
1377 is_nothrow_constructible<
1379 std::initializer_list<Up> &,
1380 Args...>::value)
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,
1390 int> = 0,
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),
1395 int> = 0>
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));
1400 return *this;
1403 template <
1404 std::size_t I,
1405 typename... Args,
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)...);
1412 template <
1413 std::size_t I,
1414 typename Up,
1415 typename... 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> &,
1419 Args...>::value,
1420 int> = 0>
1421 inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1422 return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
1425 template <
1426 typename T,
1427 typename... 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)...);
1434 template <
1435 typename T,
1436 typename Up,
1437 typename... 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> &,
1441 Args...>::value,
1442 int> = 0>
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();
1455 template <
1456 bool Dummy = true,
1457 lib::enable_if_t<lib::all<Dummy,
1458 (std::is_move_constructible<Ts>::value &&
1459 lib::is_swappable<Ts>::value)...>::value,
1460 int> = 0>
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_);
1467 private:
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);
1484 namespace detail {
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
1490 AUTO_REFREF_RETURN(
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));
1545 namespace detail {
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)
1551 : nullptr)
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);
1589 #else
1590 return lhs.index() == rhs.index() &&
1591 (lhs.valueless_by_exception() ||
1592 variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
1593 #endif
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);
1605 #else
1606 return lhs.index() != rhs.index() ||
1607 (!lhs.valueless_by_exception() &&
1608 variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
1609 #endif
1612 template <typename... Ts>
1613 inline constexpr bool operator<(const variant<Ts...> &lhs,
1614 const variant<Ts...> &rhs) {
1615 using detail::visitation::variant;
1616 using lib::less;
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);
1623 #else
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)));
1628 #endif
1631 template <typename... Ts>
1632 inline constexpr bool operator>(const variant<Ts...> &lhs,
1633 const variant<Ts...> &rhs) {
1634 using detail::visitation::variant;
1635 using lib::greater;
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);
1642 #else
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)));
1647 #endif
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);
1661 #else
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))));
1667 #endif
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);
1681 #else
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))));
1688 #endif
1691 struct monostate {};
1693 inline constexpr bool operator<(monostate, monostate) noexcept {
1694 return false;
1697 inline constexpr bool operator>(monostate, monostate) noexcept {
1698 return false;
1701 inline constexpr bool operator<=(monostate, monostate) noexcept {
1702 return true;
1705 inline constexpr bool operator>=(monostate, monostate) noexcept {
1706 return true;
1709 inline constexpr bool operator==(monostate, monostate) noexcept {
1710 return true;
1713 inline constexpr bool operator!=(monostate, monostate) noexcept {
1714 return false;
1717 #ifdef MPARK_CPP14_CONSTEXPR
1718 namespace detail {
1720 inline constexpr bool all(std::initializer_list<bool> bs) {
1721 for (bool b : bs) {
1722 if (!b) {
1723 return false;
1726 return true;
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()...})
1734 ? (void)0
1735 : throw_bad_variant_access()),
1736 detail::visitation::variant::visit_value(
1737 lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
1739 #else
1740 namespace detail {
1742 template <std::size_t N>
1743 inline constexpr bool all_impl(const lib::array<bool, N> &bs,
1744 std::size_t idx) {
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(
1758 (detail::all(
1759 lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}})
1760 ? (void)0
1761 : throw_bad_variant_access()),
1762 detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
1763 lib::forward<Vs>(vs)...))
1764 #endif
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)) {
1770 lhs.swap(rhs);
1773 namespace detail {
1775 template <typename T, typename...>
1776 using enabled_type = T;
1778 namespace hash {
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;
1796 } // namespace hash
1798 } // namespace detail
1800 #undef AUTO
1801 #undef AUTO_RETURN
1803 #undef AUTO_REFREF
1804 #undef AUTO_REFREF_RETURN
1806 #undef DECLTYPE_AUTO
1807 #undef DECLTYPE_AUTO_RETURN
1809 } // namespace mpark
1811 namespace std {
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);
1834 #else
1835 hasher{}
1836 #endif
1839 return hash_combine(result, hash<std::size_t>{}(v.index()));
1842 private:
1843 #ifndef MPARK_GENERIC_LAMBDAS
1844 struct hasher {
1845 template <typename Alt>
1846 inline std::size_t operator()(const Alt &alt) const {
1847 using alt_type = mpark::lib::decay_t<Alt>;
1848 using value_type =
1849 mpark::lib::remove_const_t<typename alt_type::value_type>;
1850 return hash<value_type>{}(alt.value);
1853 #endif
1855 static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
1856 return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
1860 template <>
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.
1870 } // namespace std
1872 #endif // MPARK_VARIANT_HPP