16 #ifndef SUMTY_VARIANT_HPP 
   17 #define SUMTY_VARIANT_HPP 
   19 #include "sumty/detail/fwd.hpp"     
   20 #include "sumty/detail/traits.hpp"  
   21 #include "sumty/detail/utils.hpp" 
   22 #include "sumty/detail/variant_impl.hpp"  
   23 #include "sumty/exceptions.hpp" 
   24 #include "sumty/utils.hpp" 
   29 #include <initializer_list> 
   30 #include <type_traits> 
   38 struct variant_size_helper;
 
   40 template <
typename... T>
 
   41 struct variant_size_helper<variant<T...>> : std::integral_constant<size_t, 
sizeof...(T)> {};
 
   43 template <
typename... T>
 
   44 struct variant_size_helper<
const variant<T...>>
 
   45     : std::integral_constant<size_t, 
sizeof...(T)> {};
 
   47 template <size_t I, 
typename T>
 
   48 struct variant_alternative_helper;
 
   50 template <size_t I, 
typename... T>
 
   51 struct variant_alternative_helper<I, variant<T...>> {
 
   52     using type = detail::select_t<I, T...>;
 
   55 template <size_t I, 
typename... T>
 
   56 struct variant_alternative_helper<I, 
const variant<T...>>
 
   57     : variant_alternative_helper<I, variant<T...>> {};
 
   59 template <size_t IDX, 
typename V, 
typename U>
 
   61 constexpr decltype(
auto) jump_table_entry(V&& visitor, U&& var) {
 
   62     if constexpr (std::is_void_v<
decltype(std::forward<U>(var)[sumty::index<IDX>])>) {
 
   63         return std::invoke(std::forward<V>(visitor), void_v);
 
   65         return std::invoke(std::forward<V>(visitor),
 
   66                            std::forward<U>(var)[sumty::index<IDX>]);
 
   70 template <
typename V, 
typename U, size_t... IDX>
 
   71 consteval auto make_jump_table([[maybe_unused]] std::index_sequence<IDX...> seq) {
 
   72     using ret_t = 
decltype(jump_table_entry<0>(std::declval<V&&>(), std::declval<U&&>()));
 
   73     return std::array<ret_t (*)(V&&, U&&), 
sizeof...(IDX)>{
 
   74         {&jump_table_entry<IDX, V, U>...}};
 
   77 template <
typename V, 
typename U, 
typename... T>
 
   78 consteval auto make_jump_table() 
noexcept {
 
   79     return make_jump_table<V, U>(std::make_index_sequence<
sizeof...(T)>{});
 
   82 template <
typename V, 
typename U, 
typename... T>
 
   83 static constexpr auto jump_table = make_jump_table<V, U, T...>();
 
   85 template <
typename V, 
typename U, 
typename... T>
 
   87 constexpr decltype(
auto) visit_impl(V&& visitor, U&& var) {
 
   88     return jump_table<V, U, T...>[var.index()](std::forward<V>(visitor),
 
   89                                                std::forward<U>(var));
 
   92 template <size_t IDX, 
typename V>
 
   93 struct alternative_info {
 
   94     static inline constexpr size_t index = IDX;
 
   95     using type = 
typename variant_alternative_helper<IDX, V>::type;
 
   98 template <size_t IDX, 
typename V, 
typename U>
 
  100 constexpr decltype(
auto) informed_jump_table_entry(V&& visitor, [[maybe_unused]] U&& var) {
 
  101     if constexpr (std::is_void_v<
decltype(std::forward<U>(var)[sumty::index<IDX>])>) {
 
  102         return std::invoke(std::forward<V>(visitor), void_v,
 
  103                            alternative_info<IDX, std::remove_cvref_t<U>>{});
 
  105         return std::invoke(std::forward<V>(visitor),
 
  106                            std::forward<U>(var)[sumty::index<IDX>],
 
  107                            alternative_info<IDX, std::remove_cvref_t<U>>{});
 
  111 template <
typename V, 
typename U, size_t... IDX>
 
  112 consteval auto make_informed_jump_table([[maybe_unused]] std::index_sequence<IDX...> seq) {
 
  114         decltype(informed_jump_table_entry<0>(std::declval<V&&>(), std::declval<U&&>()));
 
  115     return std::array<ret_t (*)(V&&, U&&), 
sizeof...(IDX)>{
 
  116         {&informed_jump_table_entry<IDX, V, U>...}};
 
  119 template <
typename V, 
typename U, 
typename... T>
 
  120 consteval auto make_informed_jump_table() 
noexcept {
 
  121     return make_informed_jump_table<V, U>(std::make_index_sequence<
sizeof...(T)>{});
 
  124 template <
typename V, 
typename U, 
typename... T>
 
  125 static constexpr auto informed_jump_table = make_informed_jump_table<V, U, T...>();
 
  127 template <
typename V, 
typename U, 
typename... T>
 
  129 constexpr decltype(
auto) visit_informed_impl(V&& visitor, U&& var) {
 
  130     return informed_jump_table<V, U, T...>[var.index()](std::forward<V>(visitor),
 
  131                                                         std::forward<U>(var));
 
  207 template <
typename... T>
 
  208 class variant : detail::variant_impl<
void, T...> {
 
  210     [[nodiscard]] 
constexpr detail::variant_impl<
void, T...>& data_() & 
noexcept {
 
  211         return *
static_cast<detail::variant_impl<
void, T...>*>(
this);
 
  214     [[nodiscard]] 
constexpr const detail::variant_impl<
void, T...>& data_()
 
  216         return *
static_cast<
const detail::variant_impl<
void, T...>*>(
this);
 
  219     [[nodiscard]] 
constexpr detail::variant_impl<
void, T...>& data_() && {
 
  220         return std::move(*
static_cast<detail::variant_impl<
void, T...>*>(
this));
 
  223     [[nodiscard]] 
constexpr const detail::variant_impl<
void, T...>& data_() 
const&& {
 
  224         return std::move(*
static_cast<
const detail::variant_impl<
void, T...>*>(
this));
 
  227     template <size_t IDX, 
typename U>
 
  228     [[nodiscard]] 
constexpr bool holds_alt_impl() 
const noexcept {
 
  229         if constexpr (IDX == 
sizeof...(T)) {
 
  231         } 
else if constexpr (std::is_same_v<detail::select_t<IDX, T...>, U>) {
 
  235                 return holds_alt_impl<IDX + 1, U>();
 
  238             return holds_alt_impl<IDX + 1, U>();
 
  242     template <size_t IDX>
 
  243     struct emplace_construct_t {};
 
  245     template <size_t IDX, 
typename U>
 
  246         requires(detail::traits<detail::select_t<IDX, T...>>::
template is_constructible<U>)
 
  247     constexpr explicit variant([[maybe_unused]] emplace_construct_t<IDX> tag, U&& value)
 
  248         : variant(std::in_place_index<IDX>, std::forward<U>(value)) {}
 
  250     template <size_t IDX, 
typename U>
 
  251         requires(!detail::traits<detail::select_t<IDX, T...>>::
template is_constructible<U>)
 
  252     constexpr explicit variant([[maybe_unused]] emplace_construct_t<IDX> tag, U&& value)
 
  253         : variant(emplace_construct_t<IDX + 1>{}, std::forward<U>(value)) {}
 
  256     constexpr variant([[maybe_unused]] detail::uninit_t tag) 
noexcept 
  257         : detail::variant_impl<
void, T...>(tag) {}
 
  259     template <size_t I, 
typename... Args>
 
  260     constexpr void uninit_emplace(Args&&... args) {
 
  261         data_().
template uninit_emplace<I>(std::forward<Args>(args)...);
 
  264     friend class error_set<T...>;
 
  266     template <
typename, 
typename>
 
  296         CONDITIONALLY_NOEXCEPT;
 
  394     template <size_t IDX, 
typename... Args>
 
  396     explicit(
sizeof...(
Args) == 0)
 
  401         constexpr variant(std::in_place_index_t<IDX> inplace, Args&&... args)
 
  402         : detail::variant_impl<
void, T...>(inplace, std::forward<Args>(args)...) {
 
  433     template <size_t IDX, 
typename U, 
typename... Args>
 
  434     constexpr variant(std::in_place_index_t<IDX> inplace,
 
  435                       std::initializer_list<U> init,
 
  437         : detail::variant_impl<
void, T...>(inplace, init, std::forward<Args>(args)...) {}
 
  468     template <
typename U, 
typename... Args>
 
  471     explicit(
sizeof...(
Args) == 0)
 
  477         : detail::variant_impl<
void, T...>(std::in_place_index<detail::index_of_v<U, T...>>,
 
  478                                            std::forward<Args>(args)...) {
 
  510     template <
typename U, 
typename V, 
typename... Args>
 
  515                       std::initializer_list<V> init,
 
  517         : detail::variant_impl<
void, T...>(std::in_place_index<detail::index_of_v<U, T...>>,
 
  519                                            std::forward<Args>(args)...) {
 
  550     template <
typename U>
 
  560         : variant(emplace_construct_t<0>{}, std::forward<U>(value)) {
 
  592     template <
typename U>
 
  599         constexpr variant(std::initializer_list<U> init)
 
  600         : variant(emplace_construct_t<0>{}, init) {
 
  615         CONDITIONALLY_NOEXCEPT;
 
  651         requires(
true && ... &&
 
  698         noexcept((
true && ... &&
 
  702         requires(
true && ... &&
 
  711     template <size_t IDX, 
typename U>
 
  712     constexpr void assign_value(U&& value) {
 
  713         if constexpr (detail::traits<detail::select_t<IDX, T...>>::
template is_assignable<
 
  716                 if constexpr (!std::is_void_v<detail::select_t<IDX, T...>>) {
 
  717                     data_().
template get<IDX>() = std::forward<U>(value);
 
  720                 data_().
template emplace<IDX>(std::forward<U>(value));
 
  723             assign_value<IDX + 1>(std::forward<U>(value));
 
  755     template <
typename U>
 
  761         assign_value<0>(std::forward<U>(rhs));
 
  794     template <
typename U>
 
  798     constexpr variant& 
operator=(std::initializer_list<U> rhs) {
 
  799         assign_value<0>(rhs);
 
  825     [[nodiscard]] 
constexpr size_t 
index() 
const noexcept { 
return data_().index(); }
 
  849     template <size_t I, 
typename... Args>
 
  852         typename detail::traits<detail::select_t<I, T...>>::
reference 
  857         data_().
template emplace<I>(std::forward<Args>(args)...);
 
  858         return data_().
template get<I>();
 
  884     template <size_t I, 
typename U, 
typename... Args>
 
  887         typename detail::traits<detail::select_t<I, T...>>::
reference 
  891         emplace(std::initializer_list<U> ilist, Args&&... args) {
 
  892         data_().
template emplace<I>(ilist, std::forward<Args>(args)...);
 
  893         return data_().
template get<I>();
 
  924     template <
typename U, 
typename... Args>
 
  935         data_().
template emplace<detail::index_of_v<U, T...>>(std::forward<Args>(args)...);
 
  936         return data_().
template get<detail::index_of_v<U, T...>>();
 
  968     template <
typename U, 
typename V, 
typename... Args>
 
  978         emplace(std::initializer_list<V> ilist, Args&&... args) {
 
  979         data_().
template emplace<detail::index_of_v<U, T...>>(ilist,
 
  980                                                               std::forward<Args>(args)...);
 
  981         return data_().
template get<detail::index_of_v<U, T...>>();
 
 1010     [[nodiscard]] 
constexpr 
 1012         typename detail::traits<detail::select_t<I, T...>>::
reference 
 1017         return data_().
template get<I>();
 
 1046     [[nodiscard]] 
constexpr 
 1053         return data_().
template get<I>();
 
 1082     [[nodiscard]] 
constexpr 
 1089         return std::move(data_()).
template get<I>();
 
 1118     [[nodiscard]] 
constexpr 
 1125         return std::move(data_()).
template get<I>();
 
 1158     template <
typename U>
 
 1162     [[nodiscard]] 
constexpr 
 1169         return this->operator[](sumty::index<detail::index_of_v<U, T...>>);
 
 1202     template <
typename U>
 
 1206     [[nodiscard]] 
constexpr 
 1213         return this->operator[](sumty::index<detail::index_of_v<U, T...>>);
 
 1246     template <
typename U>
 
 1250     [[nodiscard]] 
constexpr 
 1257         return std::move(*
this).operator[](sumty::index<detail::index_of_v<U, T...>>);
 
 1290     template <
typename U>
 
 1294     [[nodiscard]] 
constexpr 
 1301         return std::move(*
this).operator[](sumty::index<detail::index_of_v<U, T...>>);
 
 1328     [[nodiscard]] 
constexpr 
 1330         typename detail::traits<detail::select_t<I, T...>>::
reference 
 1336         return data_().
template get<I>();
 
 1363     [[nodiscard]] 
constexpr 
 1371         return data_().
template get<I>();
 
 1398     [[nodiscard]] 
constexpr 
 1406         return std::move(data_()).
template get<I>();
 
 1433     [[nodiscard]] 
constexpr 
 1441         return std::move(data_()).
template get<I>();
 
 1473     template <
typename U>
 
 1477     [[nodiscard]] 
constexpr 
 1484         return this->
template get<detail::index_of_v<U, T...>>();
 
 1516     template <
typename U>
 
 1520     [[nodiscard]] 
constexpr 
 1527         return this->
template get<detail::index_of_v<U, T...>>();
 
 1559     template <
typename U>
 
 1563     [[nodiscard]] 
constexpr 
 1570         return std::move(*
this).
template get<detail::index_of_v<U, T...>>();
 
 1602     template <
typename U>
 
 1606     [[nodiscard]] 
constexpr 
 1613         return std::move(*
this).
template get<detail::index_of_v<U, T...>>();
 
 1642     [[nodiscard]] 
constexpr 
 1644         typename detail::traits<detail::select_t<I, T...>>::
pointer 
 1649         using ptr_t = 
typename detail::traits<detail::select_t<I, T...>>::pointer;
 
 1650         if constexpr (!std::is_void_v<ptr_t>) {
 
 1653                 ret = &data_().
template get<I>();
 
 1689     [[nodiscard]] 
constexpr 
 1691         typename detail::traits<detail::select_t<I, T...>>::
const_pointer 
 1696         using ptr_t = 
typename detail::traits<detail::select_t<I, T...>>::const_pointer;
 
 1697         if constexpr (!std::is_void_v<ptr_t>) {
 
 1700                 ret = &data_().
template get<I>();
 
 1741     template <
typename U>
 
 1745     [[nodiscard]] 
constexpr 
 1747         typename detail::traits<U>::
pointer 
 1752         return get_if<detail::index_of_v<U, T...>>();
 
 1786     template <
typename U>
 
 1790     [[nodiscard]] 
constexpr 
 1797         return get_if<detail::index_of_v<U, T...>>();
 
 1818     template <
typename U>
 
 1820         if constexpr (detail::is_unique_v<U, T...>) {
 
 1821             return index() == detail::index_of_v<U, T...>;
 
 1823             return holds_alt_impl<0, U>();
 
 1857     template <
typename V>
 
 1860         detail::invoke_result_t<
 
 1862             typename detail::traits<detail::select_t<0, T...>>::
reference>
 
 1867         return detail::visit_impl<V, variant&, T...>(std::forward<V>(visitor), *
this);
 
 1900     template <
typename V>
 
 1903         detail::invoke_result_t<
 
 1910         return detail::visit_impl<V, 
const variant&, T...>(std::forward<V>(visitor), *
this);
 
 1943     template <
typename V>
 
 1946         detail::invoke_result_t<
 
 1953         return detail::visit_impl<V, variant&&, T...>(std::forward<V>(visitor),
 
 1987     template <
typename V>
 
 1990         detail::invoke_result_t<
 
 1997         return detail::visit_impl<V, 
const variant&&, T...>(std::forward<V>(visitor),
 
 2051     template <
typename V>
 
 2054         detail::invoke_result_t<
 
 2056             typename detail::traits<detail::select_t<0, T...>>::
reference,
 
 2057             detail::alternative_info<0, variant>>
 
 2062         return detail::visit_informed_impl<V, variant&, T...>(std::forward<V>(visitor),
 
 2116     template <
typename V>
 
 2119         detail::invoke_result_t<
 
 2122             detail::alternative_info<0, variant>>
 
 2127         return detail::visit_informed_impl<V, 
const variant&, T...>(
 
 2128             std::forward<V>(visitor), *
this);
 
 2181     template <
typename V>
 
 2184         detail::invoke_result_t<
 
 2187             detail::alternative_info<0, variant>>
 
 2192         return detail::visit_informed_impl<V, variant&&, T...>(std::forward<V>(visitor),
 
 2246     template <
typename V>
 
 2249         detail::invoke_result_t<
 
 2252             detail::alternative_info<0, variant>>
 
 2257         return detail::visit_informed_impl<V, 
const variant&&, T...>(
 
 2258             std::forward<V>(visitor), std::move(*
this));
 
 2287     constexpr void swap(variant& other)
 
 2294         data_().swap(other.data_());
 
 2318 template <
typename T, 
typename... U>
 
 2320     return v.
template holds_alternative<T>();
 
 2349 template <size_t I, 
typename... T>
 
 2352     typename detail::traits<detail::select_t<I, T...>>::
reference 
 2357     return v.
template get<I>();
 
 2386 template <size_t I, 
typename... T>
 
 2394     return v.
template get<I>();
 
 2423 template <size_t I, 
typename... T>
 
 2431     return std::move(v).
template get<I>();
 
 2460 template <size_t I, 
typename... T>
 
 2467     get(
const variant<T...>&& v) {
 
 2468     return std::move(v).
template get<I>();
 
 2503 template <
typename T, 
typename... U>
 
 2514     return v.
template get<T>();
 
 2549 template <
typename T, 
typename... U>
 
 2560     return v.
template get<T>();
 
 2595 template <
typename T, 
typename... U>
 
 2606     return std::move(v).
template get<T>();
 
 2641 template <
typename T, 
typename... U>
 
 2651     get(
const variant<U...>&& v) {
 
 2652     return std::move(v).
template get<T>();
 
 2683 template <size_t I, 
typename... T>
 
 2686     typename detail::traits<detail::select_t<I, T...>>::
pointer 
 2691     return v.
template get_if<I>();
 
 2722 template <size_t I, 
typename... T>
 
 2725     typename detail::traits<detail::select_t<I, T...>>::
const_pointer 
 2730     return v.
template get_if<I>();
 
 2767 template <
typename T, 
typename... U>
 
 2773     typename detail::traits<T>::
pointer 
 2778     return v.
template get_if<T>();
 
 2815 template <
typename T, 
typename... U>
 
 2826     return v.
template get_if<T>();
 
 2868 template <
typename V>
 
 2871     std::invoke_result_t<V&&>
 
 2876     return std::invoke(std::forward<V>(visitor));
 
 2922 template <
typename V, 
typename T0, 
typename... TN>
 
 2925     detail::invoke_result_t<V&&,
 
 2926                             decltype(get<0>(std::declval<T0&&>())),
 
 2927                             decltype(get<0>(std::declval<TN&&>()))...>
 
 2932     visit(V&& visitor, T0&& var0, TN&&... varn) {
 
 2933     if constexpr (
sizeof...(TN) == 0) {
 
 2934         return std::forward<T0>(var0).visit(std::forward<V>(visitor));
 
 2936         return std::forward<T0>(var0).visit(
 
 2937             [visitor = std::forward<V>(visitor),
 
 2938              ... varn = std::forward<TN>(varn)](
auto&&... value) 
mutable {
 
 2940                     [visitor = std::forward<V>(visitor),
 
 2941                      ... value = std::forward<
decltype(value)>(value)](
 
 2942                         auto&&... args) 
mutable -> 
decltype(
auto) {
 
 2943                         return std::invoke(std::forward<V>(visitor),
 
 2944                                            std::forward<
decltype(value)>(value)...,
 
 2945                                            std::forward<
decltype(args)>(args)...);
 
 2947                     std::forward<TN>(varn)...);
 
 2980 template <
typename... T>
 
 2981 constexpr void swap(variant<T...>& a, variant<T...>& b)
 
 2983     noexcept(
noexcept(
a.
swap(
b)))
 
 3005 template <
typename T>
 
 3008     : detail::variant_size_helper<T> {
 
 3027 template <
typename T>
 
 3028 static inline constexpr size_t variant_size_v = variant_size<T>::value;
 
 3049 template <size_t I, 
typename T>
 
 3050 struct variant_alternative
 
 3052     : detail::variant_alternative_helper<I, T> {
 
 3073 template <size_t I, 
typename T>
 
 3074 using variant_alternative_t = 
typename variant_alternative<I, T>::type;
 
 3077 template <
typename... T>
 
 3078     requires((
true && ... && std::is_base_of_v<never, std::remove_cvref_t<T>>))
 
 3079 class variant<T...> : 
public never {};