3#ifndef RPNX_VARIANT_HPP
4#define RPNX_VARIANT_HPP
20 template <
typename T,
typename... Ts >
24 template <
typename T,
typename... Ts >
25 struct index_of< T, T, Ts... > : std::integral_constant< std::size_t, 0 >
30 template <
typename T,
typename U,
typename... Ts >
31 struct index_of< T, U, Ts... > : std::integral_constant< std::size_t, 1 + index_of< T, Ts... >::value >
35 template <
typename Allocator,
typename... Ts >
48 template <
typename Allocator >
52 template <
typename T >
57 template <
typename Allocator2,
typename... Ts >
65 using copy_func =
void* (*)(Allocator&,
void const*);
69 using less_func = bool (*)(
void const*,
void const*);
105 template <
typename T >
108 return variant_info{.m_copy = &type_copy_func< T >, .m_less = &type_less_func< T >, .m_equals = &type_equals_func< T >, .m_three_way = &type_three_way_func< T >, .m_destroy = &type_delete_func< T >, .m_default_new = &type_default_new_func< T >, .m_new_move_from = &type_new_from_move_func< T >, .m_type_info = &
typeid(T)};
112 template <
typename T >
113 static void* type_copy_func(Allocator& allocator,
void const* source)
115 static_assert(!std::is_same_v< T, void >,
"T must not be void");
116 using alloc_triats = std::allocator_traits< Allocator >;
117 using rebound_alloc_type =
typename alloc_triats::template rebind_alloc< T >;
118 using rebound_alloc_traits = std::allocator_traits< rebound_alloc_type >;
120 rebound_alloc_type rebound_alloc(allocator);
121 T* ptr = rebound_alloc_traits::allocate(rebound_alloc, 1);
125 rebound_alloc_traits::construct(rebound_alloc, ptr,
126 *
static_cast< T const*
>(source));
130 rebound_alloc_traits::deallocate(rebound_alloc, ptr, 1);
137 template <
typename T >
138 static void type_delete_func(Allocator& allocator,
void*
object)
noexcept
140 using rebound_allocator_type =
typename std::allocator_traits< Allocator >::template rebind_alloc< T >;
141 rebound_allocator_type typed_allocator(allocator);
142 T* obj_ptr =
static_cast< T*
>(object);
143 std::allocator_traits< rebound_allocator_type >::destroy(typed_allocator, obj_ptr);
144 std::allocator_traits< rebound_allocator_type >::deallocate(typed_allocator, obj_ptr, 1);
148 template <
typename T >
149 static void* type_default_new_func(Allocator& allocator)
151 using allocator_type =
typename std::allocator_traits< Allocator >::template rebind_alloc< T >;
152 using alloc_traits = std::allocator_traits< allocator_type >;
154 allocator_type typed_allocator(allocator);
155 T* ptr = alloc_traits::allocate(typed_allocator, 1);
159 alloc_traits::construct(typed_allocator, ptr);
163 alloc_traits::deallocate(typed_allocator, ptr, 1);
170 template <
typename T >
171 static void* type_new_from_move_func(Allocator& allocator,
void* source)
173 using alloc_traits = std::allocator_traits< Allocator >;
174 using rebound_alloc_type =
typename alloc_traits::template rebind_alloc< T >;
175 using rebound_alloc_traits = std::allocator_traits< rebound_alloc_type >;
176 rebound_alloc_type reboundAlloc(allocator);
177 T* ptr = std::allocator_traits< rebound_alloc_type >::allocate(reboundAlloc, 1);
181 rebound_alloc_traits::construct(reboundAlloc, ptr, std::move(*
static_cast< T*
>(source)));
185 rebound_alloc_traits::deallocate(reboundAlloc, ptr, 1);
192 template <
typename T >
193 static bool type_less_func(
void const* lhs,
void const* rhs)
195 return *
static_cast< T const*
>(lhs) < *
static_cast< T const*
>(rhs);
199 template <
typename T >
200 static constexpr bool type_equals_func(
void const* lhs,
void const* rhs)
203 if constexpr (std::equality_comparable_with< T, T >)
205 return *
static_cast< T const*
>(lhs) == *
static_cast< T const*
>(rhs);
210 return *
static_cast< T const*
>(lhs) <=> *
static_cast< T const*
>(rhs) == std::strong_ordering::equal;
215 template <
typename T >
216 static constexpr std::strong_ordering type_three_way_func(
void const* lhs,
void const* rhs)
218 if constexpr (std::three_way_comparable_with< T, T >)
221 return std::strong_order(*
static_cast< const T*
>(lhs), *
static_cast< const T*
>(rhs));
226 const T& l = *
static_cast< const T*
>(lhs);
227 const T& r = *
static_cast< const T*
>(rhs);
229 static_assert(std::is_same<
decltype(l),
decltype(r) >::value,
"T must be the same type as T");
231 return std::strong_ordering::less;
233 return std::strong_ordering::greater;
234 return std::strong_ordering::equal;
243 template <
typename... Ts >
247 template <
typename T,
typename... Ts >
254 template <
typename T,
typename... Ts >
267 template <
typename V,
typename F,
typename R, std::
size_t N, call_type C >
271 template < std::
size_t NBegin, std::
size_t NEnd,
typename V,
typename F,
typename R, call_type C >
274 if constexpr (NBegin == NEnd - 1)
280 static constexpr std::size_t Range = (NEnd - NBegin);
281 static_assert(Range >= 2,
"Range should be at least 2");
283 static constexpr std::size_t Mid = NBegin + (Range / 2);
284 static_assert(NBegin < Mid && Mid < NEnd,
"Mid should be between NBegin and NEnd");
298 template <
typename V,
typename F,
typename R, std::
size_t N, call_type C >
303 if constexpr (std::is_same_v< R, void >)
305 func(
variant.template get_n_unchecked< N >());
310 return func(
variant.template get_n_unchecked< N >());
315 if constexpr (std::is_invocable_v< F,
decltype(
variant.template get_n_unchecked< N >()) >)
317 if constexpr (std::is_same_v< R, void >)
319 func(
variant.template get_n_unchecked< N >());
324 return func(
variant.template get_n_unchecked< N >());
329 throw std::bad_variant_access();
334 if constexpr (std::is_invocable_v< F,
decltype(
variant.template get_n_unchecked< N >()) >)
336 if constexpr (std::is_same_v< R, void >)
338 func(
variant.template get_n_unchecked< N >());
343 return func(
variant.template get_n_unchecked< N >());
346 else if constexpr (!std::is_same_v< R, void >)
354 template <
typename V,
typename F,
typename R >
358 template <
typename F,
typename R,
typename A,
typename... Vs >
362 std::array< vexecptr, std::tuple_size_v< std::tuple< Vs... > > >
result{};
364 update_variant_invoke_table_lvalue< 0, F, R, A, Vs... >(
result);
370 template <
typename V, std::
size_t N >
374 template <
typename A,
typename... Vs, std::size_t N >
379 using type = std::tuple_element_t< N, std::tuple< Vs... > >;
383 template <
typename V >
387 template <
typename A,
typename... Vs >
392 using type = std::integral_constant< std::size_t,
sizeof...(Vs) >;
394 static constexpr std::size_t
value =
sizeof...(Vs);
398 template <
typename V >
402 template <
typename V, std::
size_t N >
406 template < std::
size_t N,
typename F,
typename R,
typename V, call_type C >
410 template <
typename F,
typename R,
typename V, call_type C >
414 std::array< vexecptr, variant_size_v< std::remove_cvref_t< V > > >
result{};
422 template < std::
size_t N,
typename F,
typename R,
typename V, call_type C >
427 if constexpr (N < variant_size_v< std::remove_cvref_t< V > >)
436 template <
typename F,
typename R,
typename V, call_type C >
449 template <
typename R, dispatch_type D = dispatch_type::automatic,
typename V,
typename F >
471 template <
typename R,
typename V,
typename F >
483 template <
typename R,
typename V,
typename F >
494 template <
typename A,
typename... Ts >
505 template <
typename T2 >
508 m_val = std::forward< T2 >(other);
522 template <
typename Allocator,
typename... Ts >
525 struct variant_impl_info
530 std::size_t m_index = 0;
538 template < std::
size_t N >
539 static consteval variant_impl_info calc_info()
541 using type =
typename std::tuple_element< N, std::tuple< Ts... > >
::type;
542 variant_impl_info
result{};
545 result.m_general_info = v_info;
550 template < std::
size_t N >
551 static constexpr variant_impl_info s_v_info_for = calc_info< N >();
554 void* m_data =
nullptr;
556 variant_impl_info
const* m_vinf =
nullptr;
558 [[no_unique_address]] Allocator m_alloc;
565 template <
typename T2 >
566 static constexpr bool has_cvref_removed_identical_type()
569 return (std::is_same_v< std::remove_cvref_t< T2 >, Ts > || ...);
576 bool valueless()
const
578 return m_data ==
nullptr;
587 if (m_vinf ==
nullptr && m_data ==
nullptr)
592 if (m_vinf ==
nullptr || m_data ==
nullptr)
597 if (m_vinf->m_index >= std::tuple_size_v< std::tuple< Ts... > >)
616 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
617 m_vinf = &s_v_info_for< 0 >;
620 m_data = m_vinf->m_general_info.m_default_new(m_alloc);
637 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
642 std::swap(m_vinf, other.m_vinf);
643 std::swap(m_data, other.m_data);
645 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
660 assert((other.m_vinf ==
nullptr) == (other.m_data ==
nullptr));
662 if (other.m_vinf ==
nullptr)
666 m_vinf = other.m_vinf;
669 m_data = m_vinf->m_general_info.m_copy(m_alloc, other.m_data);
685 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
687 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
696 if (m_vinf !=
nullptr)
698 assert(m_data !=
nullptr);
699 m_vinf->m_general_info.m_destroy(m_alloc, m_data);
712 template <
typename... Ts2 >
717 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
727 template <
typename T >
734 if constexpr (std::is_same_v< std::remove_cvref_t< T >,
basic_variant< Allocator, Ts... > >)
738 else if constexpr (
requires {
typename std::remove_cvref_t< T >::value_type; })
740 if constexpr (std::is_same_v< typename std::remove_cvref_t< T >::value_type,
basic_variant< Allocator, Ts... > >)
746 return (std::is_convertible_v< T, Ts > || ...);
752 return (std::is_convertible_v< T, Ts > || ...);
763 template <
typename T2 >
766 constexpr std::size_t
index = constructor_index< T2 >();
767 using selected_type = std::tuple_element_t<
index, std::tuple< Ts... > >;
768 using rebound_alloc_type =
typename std::allocator_traits< allocator_type >::template rebind_alloc< selected_type >;
769 rebound_alloc_type rebound_alloc(m_alloc);
771 m_vinf = &s_v_info_for< index >;
772 assert(m_vinf->m_index ==
index);
773 assert(m_vinf->m_index < (std::tuple_size_v< std::tuple< Ts... > >));
778 m_data = std::allocator_traits< rebound_alloc_type >::allocate(rebound_alloc,
782 std::allocator_traits< rebound_alloc_type >::construct(rebound_alloc,
static_cast< selected_type*
>(m_data), std::forward< T2 >(value));
786 if (m_data !=
nullptr)
788 std::allocator_traits< rebound_alloc_type >::deallocate(rebound_alloc,
static_cast< selected_type*
>(m_data), 1);
804 template < typename T, std::enable_if_t< can_construct_subtype_with< T >(),
int > = 0 >
807 assert((m_vinf ==
nullptr) == (m_data ==
nullptr));
809 if (m_vinf !=
nullptr)
811 assert(m_vinf->m_index < std::tuple_size_v< std::tuple< Ts... > >);
813 auto old_vinf = m_vinf;
814 auto old_data = m_data;
819 constexpr std::size_t
index = constructor_index< T >();
820 using selected_type = std::tuple_element_t<
index, std::tuple< Ts... > >;
821 m_vinf = &s_v_info_for< index >;
822 assert(m_vinf->m_index ==
index);
823 assert(m_vinf->m_index < (std::tuple_size_v< std::tuple< Ts... > >));
826 using rebound_alloc_type =
typename std::allocator_traits< allocator_type >::template rebind_alloc< selected_type >;
827 rebound_alloc_type value_alloc(m_alloc);
830 m_data = value_alloc.allocate(1);
832 std::allocator_traits< rebound_alloc_type >::construct(value_alloc,
static_cast< selected_type*
>(m_data), std::forward< T >(value));
836 if (m_data !=
nullptr)
838 std::allocator_traits< rebound_alloc_type >::deallocate(value_alloc,
static_cast< selected_type*
>(m_data), 1);
849 if (old_vinf !=
nullptr)
851 old_vinf->m_general_info.m_destroy(m_alloc, old_data);
866 m_alloc = other.m_alloc;
868 std::swap(m_vinf, other.m_vinf);
869 std::swap(m_data, other.m_data);
884 template <
typename T >
890 if constexpr (std::is_convertible_v<
decltype(arg), T&>) {
891 return static_cast< T&
>(arg);
896 throw std::bad_variant_access();
907 template <
typename T >
911 [](
auto& arg) -> T
const&
913 if constexpr (std::is_convertible_v<
decltype(arg), T
const&>) {
914 return static_cast< T const&
>(arg);
916 throw std::bad_variant_access();
927 template <
typename T >
936 throw std::bad_variant_access();
939 return *
static_cast< T*
>(m_data);
948 template <
typename T >
957 throw std::bad_variant_access();
960 return *
static_cast< T*
>(m_data);
969 template <
typename T >
978 throw std::bad_variant_access();
981 return *
static_cast< T*
>(m_data);
990 template <
typename T >
998 return *
static_cast< T*
>(m_data);
1007 template <
typename T >
1015 return *
static_cast< T const*
>(m_data);
1024 template <
typename T >
1028 static_assert(has_cvref_removed_identical_type< T >(),
"Must be in type list");
1034 throw std::bad_variant_access();
1038 return *
static_cast< T const*
>(m_data);
1047 template <
typename T >
1051 static_assert(has_cvref_removed_identical_type< T >(),
"Must be in type list");
1057 throw std::bad_variant_access();
1061 return *
static_cast< T const*
>(m_data);
1070 template <
typename T >
1074 static_assert(has_cvref_removed_identical_type< T >(),
"Must be in type list");
1080 throw std::bad_variant_access();
1084 return *
static_cast< T const*
>(m_data);
1093 template < std::
size_t N >
1099 if (m_vinf ==
nullptr || m_vinf->m_index != N)
1102 throw std::bad_variant_access();
1107 return *
static_cast< typename std::tuple_element< N, std::tuple< Ts...
> >
::type const* >(m_data);
1116 template < std::
size_t N >
1121 return *
static_cast< typename std::tuple_element< N, std::tuple< Ts...
> >
::type const* >(m_data);
1133 if (m_vinf ==
nullptr || other.m_vinf ==
nullptr)
1135 throw std::bad_variant_access();
1137 if (m_vinf->m_index != other.m_vinf->m_index)
1142 return m_vinf->m_general_info.m_equals(m_data, other.m_data);
1154 return !(*
this == other);
1167 if (m_vinf ==
nullptr || other.m_vinf ==
nullptr)
1169 throw std::bad_variant_access();
1171 if (m_vinf->m_index != other.m_vinf->m_index)
1173 return m_vinf->m_index < other.m_vinf->m_index;
1176 return m_vinf->m_general_info.m_less(m_data, other.m_data);
1189 if (m_vinf ==
nullptr || other.m_vinf ==
nullptr)
1191 throw std::bad_variant_access();
1194 if (m_vinf->m_index != other.m_vinf->m_index)
1196 return m_vinf->m_index <=> other.m_vinf->m_index;
1198 return m_vinf->m_general_info.m_three_way(m_data, other.m_data);
1206 template <
typename T >
1211 return m_vinf !=
nullptr && m_vinf->m_index ==
index_of< T, Ts... >::value;
1219 template <
typename... Ts2 >
1223 if (m_vinf ==
nullptr)
1238 template <
typename R, dispatch_type D = dispatch_type::automatic,
typename F >
1252 template <
typename R, dispatch_type D = dispatch_type::automatic,
typename F >
1266 template <
typename R, dispatch_type D = dispatch_type::automatic,
typename F >
1280 template <
typename R,
typename F >
1294 template <
typename R,
typename F >
1308 template <
typename R,
typename F >
1322 template <
typename R,
typename F >
1335 template <
typename R,
typename F >
1348 template <
typename R,
typename F >
1360 template <
typename T,
typename F >
1378 template <
typename T,
typename F >
1395 template <
typename T,
typename F >
1414 template <
typename T,
typename F >
1430 template <
typename T >
1438 return static_cast< T*
>(m_data);
1446 template <
typename T >
1454 return static_cast< T const*
>(m_data);
1465 if (m_vinf ==
nullptr)
1467 throw std::bad_variant_access();
1469 return *m_vinf->m_general_info.m_type_info;
1480 return std::type_index(
type());
1489 template < std::
size_t N >
1493 if (m_vinf ==
nullptr || m_vinf->m_index != N)
1495 throw std::bad_variant_access();
1498 return *
static_cast< std::tuple_element_t< N, std::tuple< Ts...
> >* >(m_data);
1507 template < std::
size_t N >
1512 return *
static_cast< std::tuple_element_t< N, std::tuple< Ts...
> >* >(m_data);
1523 if (m_vinf ==
nullptr) [[unlikely]]
1525 throw std::bad_variant_access();
1527 return m_vinf->m_index;
1537 template <
typename T, std::
size_t N >
1538 static consteval std::size_t cvref_removed_identical_index()
1540 if constexpr (N >=
sizeof...(Ts))
1546 if constexpr (std::is_same_v< std::remove_cvref_t< T >, std::tuple_element_t< N, std::tuple< Ts... > > >)
1552 return cvref_removed_identical_index< T, N + 1 >();
1562 template <
typename T >
1563 static constexpr std::size_t constructor_index()
1570 if constexpr (has_cvref_removed_identical_type< T >())
1572 constexpr auto exact_index = cvref_removed_identical_index< T, 0 >();
1573 if constexpr (std::is_convertible_v< T, std::tuple_element_t< exact_index, std::tuple< Ts... > > >)
1579 return convertible_index< T, 0 >();
1584 return convertible_index< T, 0 >();
1594 template <
typename T, std::
size_t N >
1595 static constexpr std::size_t convertible_index()
1598 if constexpr (std::is_convertible_v< T, std::tuple_element_t< N, std::tuple< Ts... > > >)
1604 return convertible_index< T, N + 1 >();
Heap-backed tagged union with allocator-aware storage.
Definition variant.hpp:524
auto & get_n()
Retrieves the held value by alternative index with runtime checking.
Definition variant.hpp:1490
T & unwrap_unchecked()
Retrieves the held value as T& without runtime checks.
Definition variant.hpp:991
R apply_visitor_checked(F &&func) &
Applies a visitor and throws if not invocable for the active alternative.
Definition variant.hpp:1281
T const & static_cast_as() const
Returns the held value cast to T const& via visitor dispatch.
Definition variant.hpp:908
bool type_is() const
Checks whether the active alternative is exactly T.
Definition variant.hpp:1207
void reset()
Resets the variant to the valueless state.
Definition variant.hpp:693
R apply_visitor(F &&func) &
Applies a visitor to the active alternative.
Definition variant.hpp:1239
bool match(F &&func) const
Const overload of match().
Definition variant.hpp:1396
R try_apply_visitor(F &&func) const &
Const lvalue overload of try_apply_visitor().
Definition variant.hpp:1336
std::type_info const & type() const
Returns RTTI for the active alternative.
Definition variant.hpp:1462
bool test(F &&func) const
Const overload of test().
Definition variant.hpp:1415
bool test(F &&func)
Invokes func with the held value if it is of type T and returns predicate result.
Definition variant.hpp:1379
bool type_any_of() const
Checks whether the active alternative is any of Ts2.
Definition variant.hpp:1220
auto const & get_n_unchecked() const
Retrieves the held value by alternative index without runtime checking.
Definition variant.hpp:1117
static consteval bool can_construct_subtype_with()
Indicates whether this variant can be constructed from T.
Definition variant.hpp:728
T & get_as()
Retrieves the held value as T& with runtime type checking.
Definition variant.hpp:928
basic_variant(basic_variant< Allocator, Ts2... > const &other, std::enable_if_t< !std::is_same_v< basic_variant< Allocator, Ts... >, basic_variant< Allocator, Ts2... > > &&!has_cvref_removed_identical_type< basic_variant< Allocator, Ts2... > >(), int >=0)
Converting copy constructor from another compatible variant type.
Definition variant.hpp:713
std::strong_ordering operator<=>(basic_variant< Allocator, Ts... > const &other) const
Three-way comparison.
Definition variant.hpp:1186
T const & get_as() const
Retrieves the held value as T const& with runtime type checking.
Definition variant.hpp:1025
T const * cast_ptr() const
Const overload of cast_ptr().
Definition variant.hpp:1447
bool operator==(basic_variant< Allocator, Ts... > const &other) const
Equality comparison.
Definition variant.hpp:1130
std::allocator< void > allocator_type
Definition variant.hpp:607
R apply_visitor(F &&func) const &
Const lvalue overload of apply_visitor().
Definition variant.hpp:1253
R apply_visitor_checked(F &&func) const &
Const lvalue overload of apply_visitor_checked().
Definition variant.hpp:1295
auto const & get_n() const
Retrieves the held value by alternative index with runtime checking.
Definition variant.hpp:1094
R try_apply_visitor(F &&func) &&
Rvalue overload of try_apply_visitor().
Definition variant.hpp:1349
R apply_visitor_checked(F &&func) &&
Rvalue overload of apply_visitor_checked().
Definition variant.hpp:1309
bool operator!=(basic_variant< Allocator, Ts... > const &other) const
Inequality comparison.
Definition variant.hpp:1151
constexpr basic_variant(T2 &&value, const allocator_type &alloc=allocator_type(), std::enable_if_t< rpnx::basic_variant< Allocator, Ts... >::can_construct_subtype_with< T2 >(), int >=0)
Constructs the variant from a value convertible to one of the alternatives.
Definition variant.hpp:764
std::size_t index() const
Definition variant.hpp:1520
T const & as() const
Const alias of get_as().
Definition variant.hpp:1048
bool operator<(basic_variant< Allocator, Ts... > const &other) const
Strict-weak ordering comparison.
Definition variant.hpp:1164
T const & unwrap() const
Const alias of get_as().
Definition variant.hpp:1071
bool match(F &&func)
Invokes func with the held value if it is of type T.
Definition variant.hpp:1361
constexpr basic_variant(const allocator_type &alloc=allocator_type())
Default-constructs the first alternative.
Definition variant.hpp:614
R try_apply_visitor(F &&func) &
Applies a visitor and returns default R{} when not invocable for the active type.
Definition variant.hpp:1323
auto & get_n_unchecked()
Retrieves the held value by alternative index without runtime checking.
Definition variant.hpp:1508
basic_variant< Allocator, Ts... > & operator=(basic_variant< Allocator, Ts... > other)
Copy-assigns by value using swap semantics.
Definition variant.hpp:862
T & unwrap()
Alias of get_as().
Definition variant.hpp:970
T & static_cast_as()
Returns the held value cast to T& via visitor dispatch.
Definition variant.hpp:885
constexpr basic_variant< Allocator, Ts... > & operator=(T &&value)
Assigns from a value convertible to one of the alternatives.
Definition variant.hpp:805
std::type_index type_index() const
Returns std::type_index for the active alternative.
Definition variant.hpp:1477
~basic_variant()
Destroys the currently-held value if present.
Definition variant.hpp:683
T * cast_ptr()
Returns pointer to held value if active type is T.
Definition variant.hpp:1431
constexpr basic_variant(basic_variant< Allocator, Ts... > &&other) noexcept(std::is_nothrow_move_constructible_v< Allocator >)
Move-constructs from another variant of the same type.
Definition variant.hpp:635
R apply_visitor(F &&func) &&
Rvalue overload of apply_visitor().
Definition variant.hpp:1267
T const & unwrap_unchecked() const
Retrieves the held value as T const& without runtime checks.
Definition variant.hpp:1008
constexpr basic_variant(basic_variant< Allocator, Ts... > const &other)
Copy-constructs from another variant of the same type.
Definition variant.hpp:655
T & as()
Alias of get_as().
Definition variant.hpp:949
A generic result class that can hold either a value or an exception.
Definition result.hpp:21
Visitor that assigns its argument into a target variant.
Definition variant.hpp:496
variant_convert_to(basic_variant< A, Ts... > &val)
Binds the assignment target.
Definition variant.hpp:501
bool operator()(T2 &&other) const
Assigns a visited value into the target.
Definition variant.hpp:506
Definition variant.hpp:54
Allocator-aware erased operations used by basic_variant.
Definition variant.hpp:50
std::strong_ordering(*)(void const *, void const *) three_way_func
Strong three-way comparison operation for one alternative type.
Definition variant.hpp:73
void(*)(Allocator &, void *) noexcept delete_func
Destroys and deallocates one erased alternative.
Definition variant.hpp:67
bool(*)(void const *, void const *) less_func
Less-than comparison operation for one alternative type.
Definition variant.hpp:69
static constexpr variant_info make_variant_info()
Builds the erased operation table for an alternative.
Definition variant.hpp:106
void *(*)(Allocator &, void const *) copy_func
Allocates and copy-constructs one erased alternative.
Definition variant.hpp:65
bool(*)(void const *, void const *) equals_func
Equality comparison operation for one alternative type.
Definition variant.hpp:71
void *(*)(Allocator &) default_new_func
Allocates and default-constructs one erased alternative.
Definition variant.hpp:63
void *(*)(Allocator &, void *) new_move_from_func
Allocates an alternative by moving from erased storage.
Definition variant.hpp:75
std::tuple_element_t< N, std::tuple< Vs... > > type
Alternative type at index N.
Definition variant.hpp:379
Obtains an alternative type by index.
Definition variant.hpp:371
static constexpr std::size_t value
Number of alternative types.
Definition variant.hpp:394
std::integral_constant< std::size_t, sizeof...(Vs) > type
Integral-constant type containing the alternative count.
Definition variant.hpp:392
Obtains the number of alternatives in a variant type.
Definition variant.hpp:384
Containers, iterator adapters, callable wrappers, and value utilities.
Definition annex.hpp:14
R apply_nth_visitor_branched(std::size_t index, V &&variant, F &&func)
Dispatches an alternative index through a compile-time binary branch tree.
Definition variant.hpp:272
basic_variant< std::allocator< void >, Ts... > variant
Convenience alias for a variant using std::allocator<void>.
Definition variant.hpp:244
call_type
Policy used when a visitor cannot accept an active alternative.
Definition variant.hpp:261
@ required
Definition variant.hpp:261
@ except_on_missing
Definition variant.hpp:261
@ optional
Definition variant.hpp:261
constexpr auto & get_as(variant< Ts... > &v)
Retrieves a mutable alternative by type.
Definition variant.hpp:248
auto consteval variant_invoke_table_gen()
Generates the legacy lvalue visitor dispatch table.
Definition variant.hpp:359
R(*)(V &&, F &&) variant_invoke_executor
Function-pointer type for one erased visitor dispatch entry.
Definition variant.hpp:355
dispatch_type
Strategy used to dispatch a visitor to an active alternative.
Definition variant.hpp:264
@ automatic
Definition variant.hpp:264
@ branching
Definition variant.hpp:264
@ indirect
Definition variant.hpp:264
R try_apply_visitor(V &&variant, F &&func)
Invokes a visitor only when it accepts the active alternative.
Definition variant.hpp:484
R apply_visitor_checked(V &&variant, F &&func)
Invokes a visitor and throws when it does not accept the active alternative.
Definition variant.hpp:472
R apply_nth_visitor(V &&variant, F &&func)
Invokes a visitor for one compile-time alternative index.
Definition variant.hpp:299
typename variant_nth_member< V, N >::type variant_nth_member_t
Alternative type at an index.
Definition variant.hpp:403
R apply_visitor(V &&variant, F &&func)
Invokes a visitor for the active alternative.
Definition variant.hpp:450
auto constexpr variant_invoke_table_gen2()
Generates a visitor dispatch table.
Definition variant.hpp:411
constexpr auto variant_invoke_table2
Shared compile-time visitor dispatch table.
Definition variant.hpp:437
constexpr void update_variant_invoke_table2(std::array< variant_invoke_executor< V, F, R >, variant_size_v< std::remove_cvref_t< V > > > &table)
Populates visitor dispatch-table entries recursively.
Definition variant.hpp:423
Definition variant.hpp:21
Erased operation table for a single variant alternative.
Definition variant.hpp:79
default_new_func m_default_new
Default-allocation operation.
Definition variant.hpp:91
three_way_func m_three_way
Three-way comparison operation.
Definition variant.hpp:87
copy_func m_copy
Copy-allocation operation.
Definition variant.hpp:81
new_move_from_func m_new_move_from
Move-allocation operation.
Definition variant.hpp:93
delete_func m_destroy
Destruction and deallocation operation.
Definition variant.hpp:89
equals_func m_equals
Equality operation.
Definition variant.hpp:85
std::type_info const * m_type_info
Run-time type information for the alternative.
Definition variant.hpp:95
less_func m_less
Less-than operation.
Definition variant.hpp:83