1#ifndef DONUT_VARIANT_HPP
2#define DONUT_VARIANT_HPP
10#include <initializer_list>
26template <
typename... Ts>
32struct ConstantList {};
34template <std::size_t N,
typename Union,
auto... MemberPointers>
35struct get_n_member_pointers {
36 using type = ConstantList<MemberPointers..., &Union::head>;
39template <std::size_t N,
typename Union,
auto... MemberPointers>
40requires(N > 0)
struct get_n_member_pointers<N, Union, MemberPointers...> : get_n_member_pointers<N - 1, typename Union::Tail, MemberPointers..., &Union::tail> {};
42template <std::
size_t N,
typename Union>
43using get_n_member_pointers_t =
typename get_n_member_pointers<N, Union>::type;
45template <
auto... MemberPointers,
typename U>
46[[nodiscard]]
constexpr auto& getUnionMemberImpl(ConstantList<MemberPointers...>, U&& u)
noexcept {
47 return (std::forward<U>(u).*....*MemberPointers);
50template <std::
size_t Index,
typename U>
51[[nodiscard]]
constexpr auto& getUnionMember(U& u)
noexcept {
52 return getUnionMemberImpl(get_n_member_pointers_t<Index, U>{}, u);
55template <
typename... Ts>
57 UnionStorage() =
default;
59 template <std::size_t Index,
typename... Args>
60 UnionStorage(std::in_place_index_t<Index>, Args&&...) =
delete;
63template <
typename First,
typename... Rest>
64union UnionStorage<First, Rest...> {
65 static constexpr std::size_t size = 1 +
sizeof...(Rest);
68 using Tail = UnionStorage<Rest...>;
70 constexpr UnionStorage()
73 template <
typename... Args>
74 constexpr UnionStorage(std::in_place_index_t<0>, Args&&... args)
75 : head(std::forward<Args>(args)...) {}
77 template <std::size_t Index,
typename... Args>
78 constexpr UnionStorage(std::in_place_index_t<Index>, Args&&... args)
79 : tail(std::in_place_index<Index - 1>, std::forward<Args>(args)...) {}
81 constexpr UnionStorage(
const UnionStorage& other, std::size_t other_index) {
82 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
83 (void)(((other_index == Indices) ? (create<Indices>(getUnionMember<Indices>(other)),
true) : false) || ...);
84 }(std::make_index_sequence<size>{});
87 constexpr UnionStorage(UnionStorage&& other, std::size_t other_index) {
88 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
89 (void)(((other_index == Indices) ? (create<Indices>(std::move(getUnionMember<Indices>(other))),
true) : false) || ...);
90 }(std::make_index_sequence<size>{});
93 ~UnionStorage() =
default;
94 constexpr ~UnionStorage()
requires(!std::is_trivially_destructible_v<Head> || !std::is_trivially_destructible_v<Tail>) {}
96 UnionStorage(
const UnionStorage&) =
default;
97 UnionStorage(UnionStorage&&) =
default;
98 UnionStorage& operator=(
const UnionStorage&) =
default;
99 UnionStorage& operator=(UnionStorage&&) =
default;
101 template <std::size_t Index,
typename... Args>
102 constexpr void create(Args&&... args) {
103 std::construct_at(&getUnionMember<Index>(*
this), std::forward<Args>(args)...);
106 constexpr void destroy(std::size_t index)
noexcept {
107 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
108 (void)(((index == Indices) ? (std::destroy_at(&getUnionMember<Indices>(*
this)),
true) : false) || ...);
109 }(std::make_index_sequence<size>{});
116template <
template <
typename...>
typename Template,
typename... TemplateArgs>
117constexpr void derivedFromTemplateSpecializationTest(
const Template<TemplateArgs...>&);
119template <
typename T,
template <
typename...>
typename Template>
120concept derived_from_template_specialization_of =
requires(
const T& t) { derivedFromTemplateSpecializationTest<Template>(t); };
122template <
typename T, std::size_t Index,
typename... Ts>
123struct VariantIndexImpl;
125template <
typename T, std::size_t Index,
typename First,
typename... Rest>
126struct VariantIndexImpl<T, Index, First, Rest...> : VariantIndexImpl<T, Index + 1, Rest...> {};
128template <
typename T, std::size_t Index,
typename... Rest>
129struct VariantIndexImpl<T, Index, T, Rest...> : std::integral_constant<std::size_t, Index> {};
131template <
typename... Functors>
133 using Functors::operator()...;
136template <
typename... Functors>
143 template <
typename... Functors>
144 constexpr decltype(
auto)
operator()(Functors&&... functors)
const {
145 return visit(detail::Overloaded{std::forward<Functors>(functors)...}, variant);
152template <
typename T,
typename V>
153struct variant_has_alternative;
155template <
typename T,
typename First,
typename... Rest>
156struct variant_has_alternative<T, Variant<First, Rest...>> : variant_has_alternative<T, Variant<Rest...>> {};
159struct variant_has_alternative<T, Variant<>> : std::false_type {};
161template <
typename T,
typename... Rest>
162struct variant_has_alternative<T, Variant<T, Rest...>> : std::true_type {};
171template <
typename T,
typename V>
175template <
typename T,
typename V>
178template <
typename T,
typename... Ts>
179struct variant_index<T,
Variant<Ts...>> : detail::VariantIndexImpl<T, 0, Ts...> {};
188template <
typename T,
typename V>
192template <std::
size_t Index,
typename V>
193struct variant_alternative;
195template <std::size_t Index,
typename First,
typename... Rest>
196struct variant_alternative<Index,
Variant<First, Rest...>> : variant_alternative<Index - 1, Variant<Rest...>> {};
198template <
typename T,
typename... Rest>
199struct variant_alternative<0, Variant<T, Rest...>> {
210template <std::
size_t Index,
typename V>
217template <
typename... Ts>
218struct variant_size<
Variant<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {};
258 return std::strong_ordering::equal;
284 [[nodiscard]] const
char*
what() const noexcept
override {
285 return "Bad variant access.";
289template <
typename... Ts>
292 static constexpr bool HAS_DEFAULT_CONSTRUCTOR = std::is_default_constructible_v<variant_alternative_t<0, Variant>>;
293 static constexpr bool HAS_COPY_CONSTRUCTOR = (std::is_copy_constructible_v<Ts> && ...);
294 static constexpr bool HAS_MOVE_CONSTRUCTOR = (std::is_move_constructible_v<Ts> && ...);
295 static constexpr bool HAS_COPY_ASSIGNMENT = ((std::is_copy_constructible_v<Ts> && std::is_copy_assignable_v<Ts>) && ...);
296 static constexpr bool HAS_MOVE_ASSIGNMENT = ((std::is_move_constructible_v<Ts> && std::is_move_assignable_v<Ts>) && ...);
297 static constexpr bool HAS_TRIVIAL_COPY_CONSTRUCTOR = (std::is_trivially_copy_constructible_v<Ts> && ...);
298 static constexpr bool HAS_TRIVIAL_MOVE_CONSTRUCTOR = (std::is_trivially_move_constructible_v<Ts> && ...);
299 static constexpr bool HAS_TRIVIAL_COPY_ASSIGNMENT =
300 ((std::is_trivially_copy_constructible_v<Ts> && std::is_trivially_copy_assignable_v<Ts> && std::is_trivially_destructible_v<Ts>) && ...);
301 static constexpr bool HAS_TRIVIAL_MOVE_ASSIGNMENT =
302 ((std::is_trivially_move_constructible_v<Ts> && std::is_trivially_move_assignable_v<Ts> && std::is_trivially_destructible_v<Ts>) && ...);
303 static constexpr bool HAS_TRIVIAL_DESTRUCTOR = (std::is_trivially_destructible_v<Ts> && ...);
305 template <
typename T>
306 struct SelectAlternativeTypeOverload {
307 template <
typename U>
308 T operator()(T, U&& u)
requires(
requires { T{std::forward<U>(u)}; });
311 struct SelectAlternativeTypeOverloadSet : SelectAlternativeTypeOverload<Ts>... {
312 using SelectAlternativeTypeOverload<Ts>::operator()...;
315 template <
typename U>
316 static constexpr auto F(U&& u) ->
decltype(SelectAlternativeTypeOverloadSet{}(std::forward<U>(u), std::forward<U>(u)));
328 std::conditional_t<
sizeof...(Ts) < 255ull, std::uint8_t,
329 std::conditional_t<
sizeof...(Ts) < 65535ull, std::uint16_t,
330 std::conditional_t<
sizeof...(Ts) < 4294967295ull, std::uint32_t,
347 :
Variant(std::in_place_index<0>) {}
361 template <
typename U>
362 constexpr Variant(U&& value)
noexcept(std::is_nothrow_constructible_v<decltype(F(std::forward<U>(value)))>)
364 std::is_constructible_v<decltype(F(std::forward<U>(value))), U>)
378 template <
typename T,
typename... Args>
379 constexpr explicit Variant(std::in_place_type_t<T> type, Args&&... args)
requires(variant_has_alternative_v<T, Variant> && std::is_constructible_v<T, Args...>)
399 template <
typename T,
typename U,
typename... Args>
400 constexpr explicit Variant(std::in_place_type_t<T> type, std::initializer_list<U> ilist, Args&&... args)
401 requires(variant_has_alternative_v<T, Variant> && std::is_constructible_v<T, std::initializer_list<U>&, Args...>)
417 template <std::size_t Index,
typename... Args>
418 constexpr explicit Variant(std::in_place_index_t<Index>
index, Args&&... args)
420 : storage(
index, std::forward<Args>(args)...)
421 , activeTypeIndex(Index) {}
438 template <std::size_t Index,
typename U,
typename... Args>
439 constexpr explicit Variant(std::in_place_index_t<Index>
index, std::initializer_list<U> ilist, Args&&... args)
441 : storage(
index, ilist, std::forward<Args>(args)...)
442 , activeTypeIndex(Index) {}
450 constexpr ~Variant()
requires(HAS_TRIVIAL_DESTRUCTOR) =
default;
453 constexpr Variant(
const Variant& other)
requires(!HAS_COPY_CONSTRUCTOR) =
delete;
456 constexpr Variant(
const Variant& other)
requires(HAS_COPY_CONSTRUCTOR && HAS_TRIVIAL_COPY_CONSTRUCTOR) =
default;
459 constexpr Variant(
const Variant& other)
requires(HAS_COPY_CONSTRUCTOR && !HAS_TRIVIAL_COPY_CONSTRUCTOR)
460 : storage(other.storage, other.activeTypeIndex)
461 , activeTypeIndex(other.activeTypeIndex) {}
464 constexpr Variant(
Variant&& other)
noexcept requires(HAS_MOVE_CONSTRUCTOR && HAS_TRIVIAL_MOVE_CONSTRUCTOR) =
default;
468 (std::is_nothrow_move_constructible_v<Ts> && ...))
469 requires(HAS_MOVE_CONSTRUCTOR && !HAS_TRIVIAL_MOVE_CONSTRUCTOR)
470 : storage(std::move(other.storage), other.activeTypeIndex)
471 , activeTypeIndex(other.activeTypeIndex) {}
491 constexpr Variant&
operator=(
Variant&& other)
noexcept requires(HAS_MOVE_ASSIGNMENT && HAS_TRIVIAL_MOVE_ASSIGNMENT) =
default;
500 ((std::is_nothrow_move_constructible_v<Ts> &&
501 std::is_nothrow_move_assignable_v<Ts>) &&
502 ...))
requires(HAS_MOVE_ASSIGNMENT && !HAS_TRIVIAL_MOVE_ASSIGNMENT) {
503 if (activeTypeIndex == other.activeTypeIndex) {
504 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
505 (void)(((is<Indices>()) ? ((as<Indices>() = std::move(other.template as<Indices>())),
true) :
false) || ...);
506 }(std::make_index_sequence<
sizeof...(Ts)>{});
507 }
else if (other.activeTypeIndex ==
npos) {
511 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
512 (void)(((other.template is<Indices>()) ? ((storage.template create<Indices>(std::move(other.template as<Indices>()))),
true) :
false) || ...);
513 }(std::make_index_sequence<
sizeof...(Ts)>{});
514 activeTypeIndex = other.activeTypeIndex;
534 template <
typename U>
536 std::is_nothrow_assignable_v<decltype(F(std::forward<U>(value)))&, U> && std::is_nothrow_constructible_v<decltype(F(std::forward<U>(value))), U>)
538 std::is_assignable_v<decltype(F(std::forward<U>(value))), U>) {
539 using T =
decltype(F(std::forward<U>(value)));
541 as<T>() = std::forward<U>(value);
543 if constexpr (std::is_nothrow_constructible_v<T, U> || !std::is_nothrow_move_constructible_v<T>) {
544 emplace<T>(std::forward<U>(value));
546 emplace<T>(T(std::forward<U>(value)));
566 template <
typename T,
typename... Args>
567 constexpr T&
emplace(Args&&... args)
requires(variant_has_alternative_v<T, Variant> && std::is_constructible_v<T, Args...>) {
568 return emplace<variant_index_v<T, Variant>>(std::forward<Args>(args)...);
589 template <
typename T,
typename U,
typename... Args>
590 constexpr T&
emplace(std::initializer_list<U> ilist, Args&&... args)
591 requires(variant_has_alternative_v<T, Variant> && std::is_constructible_v<T, std::initializer_list<U>&, Args...>) {
592 return emplace<variant_index_v<T, Variant>>(ilist, std::forward<Args>(args)...);
609 template <std::size_t Index,
typename... Args>
611 static_assert(Index <
sizeof...(Ts));
613 storage.template create<Index>(std::forward<Args>(args)...);
614 activeTypeIndex = Index;
636 template <std::size_t Index,
typename U,
typename... Args>
638 requires(std::is_constructible_v<variant_alternative_t<Index, Variant>, std::initializer_list<U>&, Args...>) {
639 static_assert(Index <
sizeof...(Ts));
641 storage.template create<Index>(ilist, std::forward<Args>(args)...);
642 activeTypeIndex = Index;
659 ((std::is_nothrow_move_constructible_v<Ts> && std::is_nothrow_swappable_v<Ts>) && ...)) {
660 if (activeTypeIndex == other.activeTypeIndex) {
662 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
663 (void)(((is<Indices>()) ? ((
swap(as<Indices>(), other.template as<Indices>())),
true) :
false) || ...);
664 }(std::make_index_sequence<
sizeof...(Ts)>{});
666 Variant old = std::move(*
this);
667 *
this = std::move(other);
668 other = std::move(old);
697 return activeTypeIndex;
707 return activeTypeIndex ==
npos;
719 template <
typename T>
721 return activeTypeIndex == variant_index_v<T, Variant>;
734 template <std::
size_t Index>
735 [[nodiscard]]
constexpr bool is() const noexcept {
736 return activeTypeIndex == Index;
763 template <
typename T>
764 [[nodiscard]]
constexpr T&
as() &
noexcept requires(variant_has_alternative_v<T, Variant>) {
766 return as<variant_index_v<T, Variant>>();
793 template <
typename T>
796 return as<variant_index_v<T, Variant>>();
823 template <
typename T>
824 [[nodiscard]]
constexpr T&&
as() &&
noexcept requires(variant_has_alternative_v<T, Variant>) {
826 return std::move(
as<variant_index_v<T, Variant>>());
853 template <
typename T>
856 return std::move(
as<variant_index_v<T, Variant>>());
884 template <std::
size_t Index>
887 return detail::getUnionMember<Index>(storage);
915 template <std::
size_t Index>
918 return detail::getUnionMember<Index>(storage);
946 template <std::
size_t Index>
949 return std::move(detail::getUnionMember<Index>(storage));
977 template <std::
size_t Index>
980 return std::move(detail::getUnionMember<Index>(storage));
997 template <
typename T>
998 [[nodiscard]]
constexpr T&
get() &
requires(variant_has_alternative_v<T, Variant>) {
1019 template <
typename T>
1041 template <
typename T>
1042 [[nodiscard]]
constexpr T&&
get() &&
1043 requires(variant_has_alternative_v<T, Variant>) {
1047 return std::move(as<T>());
1064 template <
typename T>
1069 return std::move(as<T>());
1087 template <std::
size_t Index>
1110 template <std::
size_t Index>
1133 template <std::
size_t Index>
1138 return std::move(as<Index>());
1156 template <std::
size_t Index>
1161 return std::move(as<Index>());
1177 template <
typename T>
1179 return (is<T>()) ? &as<T>() :
nullptr;
1196 template <
typename T>
1198 return (is<T>()) ? &as<T>() :
nullptr;
1214 template <std::
size_t Index>
1216 return (is<Index>()) ? &as<Index>() :
nullptr;
1233 template <std::
size_t Index>
1235 return (is<Index>()) ? &as<Index>() :
nullptr;
1255 template <
typename Visitor,
typename V>
1256 static constexpr decltype(
auto)
visit(Visitor&& visitor, V&& variant) {
1257 constexpr bool IS_ALL_LVALUE_REFERENCE =
1258 (std::is_lvalue_reference_v<decltype(std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).template as<Ts>()))> && ...);
1259 constexpr bool IS_ANY_CONST =
1260 (std::is_const_v<std::remove_reference_t<decltype(std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).template as<Ts>()))>> || ...);
1261 using R = std::common_type_t<decltype(std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).template as<Ts>()))...>;
1262 if constexpr (std::is_void_v<R>) {
1263 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
1264 if (!(((variant.template is<Indices>()) ? (std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).
template as<Indices>()),
true) :
false) || ...)) {
1267 }(std::make_index_sequence<
sizeof...(Ts)>{});
1268 }
else if constexpr (IS_ALL_LVALUE_REFERENCE) {
1269 std::conditional_t<IS_ANY_CONST, const R*, R*> result =
nullptr;
1270 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
1271 if (!(((variant.template is<Indices>()) ? ((result = &std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).template as<Indices>())),
true)
1276 }(std::make_index_sequence<
sizeof...(Ts)>{});
1279 std::optional<R> result{};
1280 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
1281 if (!(((variant.template is<Indices>()) ? (result.emplace(std::invoke(std::forward<Visitor>(visitor), std::forward<V>(variant).template as<Indices>())),
true)
1286 }(std::make_index_sequence<
sizeof...(Ts)>{});
1287 return R{std::move(*result)};
1292 void destroy() noexcept {
1293 if constexpr (!HAS_TRIVIAL_DESTRUCTOR) {
1294 storage.destroy(activeTypeIndex);
1296 activeTypeIndex =
npos;
1299 detail::UnionStorage<Ts..., Monostate> storage;
1320template <
typename Visitor, detail::derived_from_
template_specialization_of<Variant> V>
1321constexpr decltype(
auto)
visit(Visitor&& visitor, V&& variant) {
1322 return std::remove_cvref_t<V>::visit(std::forward<Visitor>(visitor), std::forward<V>(variant));
1338template <
typename T,
typename... Ts>
1340 return variant.template is<T>();
1356template <std::size_t Index,
typename... Ts>
1357[[nodiscard]]
constexpr bool holds_alternative(
const Variant<Ts...>& variant)
noexcept {
1358 return variant.template is<Index>();
1376template <
typename T,
typename... Ts>
1378 return variant.template get<T>();
1396template <
typename T,
typename... Ts>
1398 return variant.template get<T>();
1416template <std::size_t Index,
typename... Ts>
1418 return variant.template get<Index>();
1436template <std::size_t Index,
typename... Ts>
1438 return variant.template get<Index>();
1456template <
typename T,
typename... Ts>
1459 return variant->template get_if<T>();
1478template <
typename T,
typename... Ts>
1481 return variant->template get_if<T>();
1499template <std::size_t Index,
typename... Ts>
1502 return variant->template get_if<Index>();
1520template <std::size_t Index,
typename... Ts>
1523 return variant->template get_if<Index>();
1538template <
typename... Ts>
1546 return visit([&]<
typename T>(
const T& value) ->
bool {
return value == b.template as<T>(); }, a);
1561template <
typename... Ts>
1569 return visit([&]<
typename T>(
const T& value) ->
bool {
return value != b.template as<T>(); }, a);
1584template <
typename... Ts>
1598 return visit([&]<
typename T>(
const T& value) ->
bool {
return value < b.template as<T>(); }, a);
1613template <
typename... Ts>
1627 return visit([&]<
typename T>(
const T& value) ->
bool {
return value <= b.template as<T>(); }, a);
1642template <
typename... Ts>
1656 return visit([&]<
typename T>(
const T& value) ->
bool {
return value > b.template as<T>(); }, a);
1671template <
typename... Ts>
1685 return visit([&]<
typename T>(
const T& value) ->
bool {
return value >= b.template as<T>(); }, a);
1700template <
typename... Ts>
1703 return std::strong_ordering::equal;
1706 return std::strong_ordering::less;
1709 return std::strong_ordering::greater;
1714 return visit([&]<
typename T>(
const T& value) -> std::common_comparison_category_t<std::compare_three_way_result_t<Ts>...> {
return value <=> b.template as<T>(); }, a);
1735template <
typename V>
1736[[nodiscard]]
constexpr detail::Matcher<V>
match(V&& variant) {
1737 return detail::Matcher<V>{std::forward<V>(variant)};
1745template <
typename... Ts>
1749 return visit(hasher, variant);
1753 template <
typename T>
1756 [[nodiscard]] std::size_t operator()(
const T& value)
const {
1757 return hasher(value);
1761 [[no_unique_address]] std::hash<T> hasher{};
1764 class HashVisitor :
public Hash<Ts>... {
1766 using Hash<Ts>::operator()...;
1769 [[no_unique_address]] HashVisitor hasher{};
Tagged union value type that holds a value of one of the given types.
Definition Variant.hpp:290
constexpr Variant(std::in_place_index_t< Index > index, Args &&... args)
Construct a variant alternative in-place given its index.
Definition Variant.hpp:418
constexpr variant_alternative_t< Index, Variant > && get() &&
Access the underlying value with the given index.
Definition Variant.hpp:1134
constexpr const T & as() const &noexcept
Access the underlying value with the given type without a safety check.
Definition Variant.hpp:794
constexpr index_type index() const noexcept
Get the alternative index of the currently active value held by the variant.
Definition Variant.hpp:696
constexpr T & as() &noexcept
Access the underlying value with the given type without a safety check.
Definition Variant.hpp:764
constexpr Variant(Variant &&other) noexcept((std::is_nothrow_move_constructible_v< Ts > &&...))
Move constructor.
Definition Variant.hpp:467
constexpr Variant(Variant &&other) noexcept=default
Trivial move constructor.
constexpr const T && as() const &&noexcept
Access the underlying value with the given type without a safety check.
Definition Variant.hpp:854
constexpr ~Variant()
Destructor.
Definition Variant.hpp:445
constexpr variant_alternative_t< Index, Variant > & emplace(Args &&... args)
Construct an alternative given its index, destroying the old value.
Definition Variant.hpp:610
constexpr T && get() &&
Access the underlying value with the given type.
Definition Variant.hpp:1042
constexpr variant_alternative_t< Index, Variant > & as() &noexcept
Access the underlying value with the given index without a safety check.
Definition Variant.hpp:885
constexpr Variant & operator=(U &&value) noexcept(std::is_nothrow_assignable_v< decltype(F(std::forward< U >(value)))&, U > &&std::is_nothrow_constructible_v< decltype(F(std::forward< U >(value))), U >)
Converting assignment.
Definition Variant.hpp:535
constexpr Variant() noexcept(std::is_nothrow_default_constructible_v< variant_alternative_t< 0, Variant > >)
Default-construct a variant with the first variant alternative, if it is default-constructible.
Definition Variant.hpp:346
constexpr Variant(std::in_place_type_t< T > type, std::initializer_list< U > ilist, Args &&... args)
Construct a variant alternative in-place given its type, with an initializer list as the first constr...
Definition Variant.hpp:400
constexpr const variant_alternative_t< Index, Variant > && as() const &&noexcept
Access the underlying value with the given index without a safety check.
Definition Variant.hpp:978
constexpr Variant(std::in_place_type_t< T > type, Args &&... args)
Construct a variant alternative in-place given its type.
Definition Variant.hpp:379
constexpr T * get_if() noexcept
Access the underlying value with the given type if it is the currently active alternative.
Definition Variant.hpp:1178
constexpr const variant_alternative_t< Index, Variant > & as() const &noexcept
Access the underlying value with the given index without a safety check.
Definition Variant.hpp:916
constexpr T && as() &&noexcept
Access the underlying value with the given type without a safety check.
Definition Variant.hpp:824
constexpr const variant_alternative_t< Index, Variant > && get() const &&
Access the underlying value with the given index.
Definition Variant.hpp:1157
constexpr const variant_alternative_t< Index, Variant > & get() const &
Access the underlying value with the given index.
Definition Variant.hpp:1111
constexpr variant_alternative_t< Index, Variant > && as() &&noexcept
Access the underlying value with the given index without a safety check.
Definition Variant.hpp:947
constexpr bool is() const noexcept
Check if the variant currently holds the alternative with the given index.
Definition Variant.hpp:735
constexpr Variant & operator=(const Variant &other)
Copy assignment.
Definition Variant.hpp:485
constexpr void swap(Variant &other) noexcept(((std::is_nothrow_move_constructible_v< Ts > &&std::is_nothrow_swappable_v< Ts >) &&...))
Swap this variant's value with that of another.
Definition Variant.hpp:658
constexpr Variant(U &&value) noexcept(std::is_nothrow_constructible_v< decltype(F(std::forward< U >(value)))>)
Converting constructor.
Definition Variant.hpp:362
friend constexpr void swap(Variant &a, Variant &b) noexcept(noexcept(a.swap(b)))
Swap the values of two variants.
Definition Variant.hpp:685
constexpr const T * get_if() const noexcept
Access the underlying value with the given type if it is the currently active alternative.
Definition Variant.hpp:1197
constexpr Variant(const Variant &other)=default
Trivial copy constructor.
constexpr variant_alternative_t< Index, Variant > & get() &
Access the underlying value with the given index.
Definition Variant.hpp:1088
constexpr Variant & operator=(const Variant &other)=delete
Deleted copy assignment.
constexpr variant_alternative_t< Index, Variant > & emplace(std::initializer_list< U > ilist, Args &&... args)
Construct an alternative given its index, with an initializer list as the first constructor argument,...
Definition Variant.hpp:637
std::conditional_t< sizeof...(Ts)< 255ull, std::uint8_t, std::conditional_t< sizeof...(Ts)< 65535ull, std::uint16_t, std::conditional_t< sizeof...(Ts)< 4294967295ull, std::uint32_t, std::uint64_t > > > index_type
Index type used to encode the active alternative type.
Definition Variant.hpp:331
constexpr T & emplace(Args &&... args)
Construct an alternative given its type, destroying the old value.
Definition Variant.hpp:567
constexpr bool is() const noexcept
Check if the variant currently holds the alternative with the given type.
Definition Variant.hpp:720
constexpr const T & get() const &
Access the underlying value with the given type.
Definition Variant.hpp:1020
constexpr Variant(const Variant &other)=delete
Deleted copy constructor.
constexpr Variant(const Variant &other)
Copy constructor.
Definition Variant.hpp:459
constexpr bool valueless_by_exception() const noexcept
Check if the variant is in the valueless by exception state.
Definition Variant.hpp:706
constexpr Variant & operator=(Variant &&other) noexcept(((std::is_nothrow_move_constructible_v< Ts > &&//NOLINT(performance-noexcept-move-constructor, cppcoreguidelines-noexcept-move-operations) std::is_nothrow_move_assignable_v< Ts >) &&...))
Move assignment.
Definition Variant.hpp:499
constexpr T & emplace(std::initializer_list< U > ilist, Args &&... args)
Construct an alternative given its type, with an initializer list as the first constructor argument,...
Definition Variant.hpp:590
static constexpr index_type npos
Invalid alternative index, representing the valueless by exception state.
Definition Variant.hpp:337
static constexpr decltype(auto) visit(Visitor &&visitor, V &&variant)
Call a visitor functor with the currently active underlying value of a variant.
Definition Variant.hpp:1256
constexpr const T && get() const &&
Access the underlying value with the given type.
Definition Variant.hpp:1065
constexpr Variant(std::in_place_index_t< Index > index, std::initializer_list< U > ilist, Args &&... args)
Construct a variant alternative in-place given its index, with an initializer list as the first const...
Definition Variant.hpp:439
constexpr Variant & operator=(Variant &&other) noexcept=default
Trivial move assignment.
constexpr Variant & operator=(const Variant &other)=default
Trivial copy assignment.
constexpr const variant_alternative_t< Index, Variant > * get_if() const noexcept
Access the underlying value with the given index if it is the currently active alternative.
Definition Variant.hpp:1234
constexpr T & get() &
Access the underlying value with the given type.
Definition Variant.hpp:998
constexpr variant_alternative_t< Index, Variant > * get_if() noexcept
Access the underlying value with the given index if it is the currently active alternative.
Definition Variant.hpp:1215
constexpr ~Variant()=default
Trivial destructor.
std::size_t operator()(const donut::Monostate &) const
Definition Variant.hpp:269
std::size_t operator()(const donut::Variant< Ts... > &variant) const
Definition Variant.hpp:1748
Definition Application.hpp:9
constexpr T & get(Variant< Ts... > &variant)
Access the underlying value with the given type of a variant.
Definition Variant.hpp:1377
constexpr decltype(auto) visit(Visitor &&visitor, V &&variant)
Call a visitor functor with the currently active underlying value of a variant.
Definition Variant.hpp:1321
constexpr bool operator!=(const Variant< Ts... > &a, const Variant< Ts... > &b)
Compare two variants for inequality.
Definition Variant.hpp:1562
Overloaded(Functors...) -> Overloaded< Functors... >
constexpr bool holds_alternative(const Variant< Ts... > &variant) noexcept
Check if a variant currently holds the alternative with the given type.
Definition Variant.hpp:1339
constexpr bool operator==(Monostate, Monostate) noexcept
Compare two monostates for equality.
Definition Variant.hpp:245
constexpr std::size_t variant_index_v
Get the index of the variant alternative with a given type in a variant type.
Definition Variant.hpp:189
constexpr bool operator<=(const Variant< Ts... > &a, const Variant< Ts... > &b)
Check if a variant is less than or equal to another variant.
Definition Variant.hpp:1614
constexpr detail::Matcher< V > match(V &&variant)
Choose a function overload to execute based on the active alternative of a variant.
Definition Variant.hpp:1736
constexpr std::size_t variant_size_v
Get the number of alternative types of a variant type.
Definition Variant.hpp:227
constexpr bool operator>=(const Variant< Ts... > &a, const Variant< Ts... > &b)
Check if a variant is greater than or equal to another variant.
Definition Variant.hpp:1672
constexpr bool variant_has_alternative_v
Check if a variant type has a given type as one of its possible alternatives.
Definition Variant.hpp:172
constexpr bool operator<(const Variant< Ts... > &a, const Variant< Ts... > &b)
Check if a variant is less than another variant.
Definition Variant.hpp:1585
constexpr bool operator>(const Variant< Ts... > &a, const Variant< Ts... > &b)
Check if a variant is greater than another variant.
Definition Variant.hpp:1643
constexpr T * get_if(Variant< Ts... > *variant) noexcept
Access the underlying value with the given type of a variant if it is the currently active alternativ...
Definition Variant.hpp:1457
typename variant_alternative< Index, V >::type variant_alternative_t
Get the type of the variant alternative with a given index in a variant type.
Definition Variant.hpp:211
constexpr std::strong_ordering operator<=>(Monostate, Monostate) noexcept
Compare two monostates.
Definition Variant.hpp:257
Exception type that is thrown on an attempt to erroneously access an inactive alternative of a Varian...
Definition Variant.hpp:281
BadVariantAccess() noexcept=default
const char * what() const noexcept override
Definition Variant.hpp:284
Unit type for representing an empty alternative in Variant.
Definition Variant.hpp:235