sumty  0.1.0
Better sum types for C++
variant.hpp
1 /* Copyright 2023 Jack A Bernard Jr.
2  *
3  * Licensed under the Apache License, Version 2.0 (the License);
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an AS IS BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef SUMTY_VARIANT_HPP
17 #define SUMTY_VARIANT_HPP
18 
19 #include "sumty/detail/fwd.hpp" // IWYU pragma: export
20 #include "sumty/detail/traits.hpp" // IWYU pragma: export
21 #include "sumty/detail/utils.hpp"
22 #include "sumty/detail/variant_impl.hpp" // IWYU pragma: export
23 #include "sumty/exceptions.hpp"
24 #include "sumty/utils.hpp"
25 
26 #include <array>
27 #include <cstddef>
28 #include <functional>
29 #include <initializer_list>
30 #include <type_traits>
31 #include <utility>
32 
33 namespace sumty {
34 
35 namespace detail {
36 
37 template <typename T>
38 struct variant_size_helper;
39 
40 template <typename... T>
41 struct variant_size_helper<variant<T...>> : std::integral_constant<size_t, sizeof...(T)> {};
42 
43 template <typename... T>
44 struct variant_size_helper<const variant<T...>>
45  : std::integral_constant<size_t, sizeof...(T)> {};
46 
47 template <size_t I, typename T>
48 struct variant_alternative_helper;
49 
50 template <size_t I, typename... T>
51 struct variant_alternative_helper<I, variant<T...>> {
52  using type = detail::select_t<I, T...>;
53 };
54 
55 template <size_t I, typename... T>
56 struct variant_alternative_helper<I, const variant<T...>>
57  : variant_alternative_helper<I, variant<T...>> {};
58 
59 template <size_t IDX, typename V, typename U>
60 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
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);
64  } else {
65  return std::invoke(std::forward<V>(visitor),
66  std::forward<U>(var)[sumty::index<IDX>]);
67  }
68 }
69 
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>...}};
75 }
76 
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)>{});
80 }
81 
82 template <typename V, typename U, typename... T>
83 static constexpr auto jump_table = make_jump_table<V, U, T...>();
84 
85 template <typename V, typename U, typename... T>
86 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
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));
90 }
91 
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;
96 };
97 
98 template <size_t IDX, typename V, typename U>
99 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
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>>{});
104  } else {
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>>{});
108  }
109 }
110 
111 template <typename V, typename U, size_t... IDX>
112 consteval auto make_informed_jump_table([[maybe_unused]] std::index_sequence<IDX...> seq) {
113  using ret_t =
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>...}};
117 }
118 
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)>{});
122 }
123 
124 template <typename V, typename U, typename... T>
125 static constexpr auto informed_jump_table = make_informed_jump_table<V, U, T...>();
126 
127 template <typename V, typename U, typename... T>
128 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
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));
132 }
133 
134 } // namespace detail
135 
136 /// @class variant variant.hpp <sumty/variant.hpp>
137 /// @brief General discriminated union
138 ///
139 /// @details
140 /// @ref variant is the fundamental sum type of sumty. @ref option, @ref
141 /// result, and @ref error_set are defined in terms of @ref variant.
142 ///
143 /// @ref variant is very similar to `std::variant`, but it does have some
144 /// key differences. Most notably, @ref variant does not support type-based
145 /// alternative selection unless all alternatives have a distinct type. For
146 /// example, `std::variant` will allow the code shown below, but @ref variant
147 /// will not.
148 ///
149 /// ```cpp
150 /// std::variant<int, int> v = 42;
151 /// ```
152 ///
153 /// Any such functionality from `std::variant` that is similarly ambiguous to
154 /// the reader is disallowed by @ref variant. Otherwise, the interface provided
155 /// by @ref variant is identical to `std::variant`, but with some additional
156 /// functions available.
157 ///
158 /// Another key difference from `std::variant` is that @ref variant allows
159 /// alternatives to have `void` and references (both lvalue and rvalue) as
160 /// types. When using an lvalue reference as an alternative type, copy and move
161 /// semantics applied to the @ref variant are the same as a raw pointer (both
162 /// trivial), instead of immovability of lvalue references.
163 ///
164 /// A more subtle, but important, difference from `std::variant` is that @ref
165 /// variant makes size optimizations for several special cases. These special
166 /// cases revolve around alternatives with types that are lvalue references,
167 /// `void`, and empty types (such as `std::monostate`).
168 ///
169 /// `void` and empty types need not occupy any memory at runtime, despite the
170 /// fact that `sizeof(<empty-type>) == 1` in C++. A @ref variant consisting
171 /// entirely of alternatives with types that are `void` or empty types only
172 /// takes up enough space to store a discriminant, which is always the smallest
173 /// possible integral type necessary to store the value `N - 1`, where `N` is
174 /// the number of alternatives. Here are some examples:
175 ///
176 /// ```cpp
177 /// struct empty_t {};
178 ///
179 /// assert(std::is_empty_v<variant<void>>);
180 ///
181 /// assert(std::is_empty_v<variant<empty_t>>);
182 ///
183 /// assert(sizeof(variant<void, empty_t>) == sizeof(bool));
184 ///
185 /// assert(sizeof(variant<empty_t, ...>) // repeated 256 times
186 /// == sizeof(uint8_t));
187 ///
188 /// assert(sizeof(variant<empty_t, ...>) // repeated 257 times
189 /// == sizeof(uint16_t));
190 /// ```
191 ///
192 /// lvalue references have the invariant that the underlying pointer is not
193 /// null. This means in cases where there are only two alternatives, with one
194 /// being an lvalue reference and the other being `void` or an empty type, null
195 /// and non-null can be used as the discriminanting values instead of having a
196 /// separate discriminant. Here are some more examples:
197 ///
198 /// ```cpp
199 /// struct empty_t {};
200 ///
201 /// assert(sizeof(variant<int&, void>) == sizeof(int*));
202 ///
203 /// assert(sizeof(variant<empty_t, int&>) == sizeof(int*));
204 /// ```
205 ///
206 /// @tparam T @ref variant alternative types
207 template <typename... T>
208 class variant : detail::variant_impl<void, T...> {
209  private:
210  [[nodiscard]] constexpr detail::variant_impl<void, T...>& data_() & noexcept {
211  return *static_cast<detail::variant_impl<void, T...>*>(this);
212  }
213 
214  [[nodiscard]] constexpr const detail::variant_impl<void, T...>& data_()
215  const& noexcept {
216  return *static_cast<const detail::variant_impl<void, T...>*>(this);
217  }
218 
219  [[nodiscard]] constexpr detail::variant_impl<void, T...>& data_() && {
220  return std::move(*static_cast<detail::variant_impl<void, T...>*>(this));
221  }
222 
223  [[nodiscard]] constexpr const detail::variant_impl<void, T...>& data_() const&& {
224  return std::move(*static_cast<const detail::variant_impl<void, T...>*>(this));
225  }
226 
227  template <size_t IDX, typename U>
228  [[nodiscard]] constexpr bool holds_alt_impl() const noexcept {
229  if constexpr (IDX == sizeof...(T)) {
230  return false;
231  } else if constexpr (std::is_same_v<detail::select_t<IDX, T...>, U>) {
232  if (index() == IDX) {
233  return true;
234  } else {
235  return holds_alt_impl<IDX + 1, U>();
236  }
237  } else {
238  return holds_alt_impl<IDX + 1, U>();
239  }
240  }
241 
242  template <size_t IDX>
243  struct emplace_construct_t {};
244 
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)) {}
249 
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)) {}
254 
255  // NOLINTNEXTLINE(hicpp-explicit-conversions)
256  constexpr variant([[maybe_unused]] detail::uninit_t tag) noexcept
257  : detail::variant_impl<void, T...>(tag) {}
258 
259  template <size_t I, typename... Args>
260  constexpr void uninit_emplace(Args&&... args) {
261  data_().template uninit_emplace<I>(std::forward<Args>(args)...);
262  }
263 
264  friend class error_set<T...>;
265 
266  template <typename, typename>
267  friend class result;
268 
269  public:
270  /// @brief Default constructor
271  ///
272  /// @details
273  /// Initializes the @ref variant such that it contains a default
274  /// constructed value of the first (index 0) alternative.
275  ///
276  /// The first alternative *must* be default constructible for this
277  /// constructor to participate in overload resoltuion, but no other
278  /// alternatives need be default constructible.
279  ///
280  /// ## Example
281  /// ```cpp
282  /// variant<int, bool, int> v;
283  ///
284  /// assert(holds_alternative<int>(v));
285  ///
286  /// assert(v.index() == 0);
287  ///
288  /// assert(get<0>(v) == int{});
289  /// ```
290  constexpr variant()
291 #ifndef DOXYGEN
294  = default;
295 #else
296  CONDITIONALLY_NOEXCEPT;
297 #endif
298 
299  /// @brief Copy constructor
300  ///
301  /// @details
302  /// A new @ref variant is initialized such that it contains a copy
303  /// constructed instance of the alternative contained in the source @ref
304  /// variant. If the source @ref variant has more than one alternative of
305  /// the same type, the new @ref variant will contain the alternative of the
306  /// same index.
307  ///
308  /// All alternative types *must* be copy constructible for this constructor
309  /// to participate in overload resolution.
310  ///
311  /// ## Example
312  /// ```cpp
313  /// variant<int, bool, int> v1{std::in_place_index<2>, 42};
314  ///
315  /// variant<int, bool, int> v2{v1};
316  ///
317  /// assert(holds_alternative<int>(v2));
318  ///
319  /// assert(v2.index() == 2);
320  ///
321  /// assert(get<2>(v2) == 42);
322  /// ```
323  constexpr variant(const variant&)
324 #ifndef DOXYGEN
325  requires(true && ... && detail::traits<T>::is_copy_constructible)
326  = default;
327 #else
328  ;
329 #endif
330 
331  /// @brief Move constructor
332  ///
333  /// @details
334  /// A new @ref variant is initialized such that it contains a move
335  /// constructed instance of the alternative contained in the source @ref
336  /// variant. If the source @ref vairant has more than one alternative of
337  /// the same type, the new @ref variant will contain the alternative of the
338  /// same index.
339  ///
340  /// All alternative types *must* be move constructible for this constructor
341  /// to participate in overload resolution.
342  ///
343  /// The source variant will continue to contain an instance of the same
344  /// alternative, but the value of the alternative after being moved depends
345  /// on the move constructor of the type. In general, moved values are said
346  /// to be in a valid, but unspecified, state.
347  ///
348  /// ## Example
349  /// ```cpp
350  /// variant<int, bool, int> v1{std::in_place_index<2>, 42};
351  ///
352  /// variant<int, bool, int> v2{std::move(v1)};
353  ///
354  /// assert(holds_alternative<int>(v2));
355  ///
356  /// assert(v2.index() == 2);
357  ///
358  /// assert(get<2>(v2) == 42);
359  /// ```
360  constexpr variant(variant&&)
361 #ifndef DOXYGEN
362  noexcept((true && ... && detail::traits<T>::is_nothrow_move_constructible))
363  requires(true && ... && detail::traits<T>::is_move_constructible)
364  = default;
365 #else
366  ;
367 #endif
368 
369  /// @brief Index emplacement constructor
370  ///
371  /// @details
372  /// A new @ref variant is initialized such that it contains a newly
373  /// constructed instance of the alternative with the specified index.
374  /// The arguments following `inplace` are forwarded directly to the
375  /// constructor of the alternative type.
376  ///
377  /// Given that `U` is the type of the alternative at the specified index,
378  /// this constructor is always valid as long as `U` is constructible with
379  /// the arguments, `std::forward<Args>(args)...`.
380  ///
381  /// ## Example
382  /// ```cpp
383  /// variant<int, std::string> v{std::in_place_index<1>, 5, 'a'};
384  ///
385  /// assert(holds_alternative<std::string>(v));
386  ///
387  /// assert(v.index() == 1);
388  ///
389  /// assert(get<1>(v) == "aaaaa");
390  /// ```
391  ///
392  /// @param inplace Constructor tag that specifies the alternative index.
393  /// @param args Arguments used to construct the alternative.
394  template <size_t IDX, typename... Args>
395 #ifndef DOXYGEN
396  explicit(sizeof...(Args) == 0)
397 #else
399 #endif
400  // NOLINTNEXTLINE(hicpp-explicit-conversions)
401  constexpr variant(std::in_place_index_t<IDX> inplace, Args&&... args)
402  : detail::variant_impl<void, T...>(inplace, std::forward<Args>(args)...) {
403  }
404 
405  /// @brief Index emplacement constructor with `std::initializer_list`
406  ///
407  /// @details
408  /// A new @ref variant is initialized such that it contains a newly
409  /// constructed instance of the alternative with the specified index.
410  /// The arguments following `inplace` are forwarded directly to the
411  /// constructor of the alternative type.
412  ///
413  /// Given that `U` is the type of the alternative at the specified index,
414  /// this constructor is always valid as long as `U` is constructible with
415  /// the arguments, `init, std::forward<Args>(args)...`.
416  ///
417  /// ## Example
418  /// ```cpp
419  /// variant<int, std::vector<int>> v{
420  /// std::in_place_index<1>,
421  /// {1, 2, 3, 4, 5}};
422  ///
423  /// assert(holds_alternative<std::vector<int>>(v));
424  ///
425  /// assert(v.index() == 1);
426  ///
427  /// assert(get<1>(v).size() == 5);
428  /// ```
429  ///
430  /// @param inplace Constructor tag that specifies the alternative index.
431  /// @param init Initializer list forwarded to the alternative constructor
432  /// @param args Additional arguments used to construct the alternative.
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,
436  Args&&... args)
437  : detail::variant_impl<void, T...>(inplace, init, std::forward<Args>(args)...) {}
438 
439  /// @brief Type emplacement constructor
440  ///
441  /// @details
442  /// A new @ref variant is initialized such that it contains a newly
443  /// constructed instance of the alternative with the specified type.
444  /// The arguments following `inplace` are forwarded directory to the
445  /// constructor of the alternative type.
446  ///
447  /// This constructor only participates in overload resolution if the
448  /// alternative type, `U`, is unique among all alternatives of the @ref
449  /// variant. That is, `variant<A, B, A>`, cannot use this constructor to
450  /// initialize an alternative of type `A`, but it could use this
451  /// constructor to initialize the alternative of type `B`. This constraint
452  /// is imposed to prevent ambiguity to the reader. Use the index based
453  /// emplacement constructor instead to initialize the alternative of type
454  /// `A`.
455  ///
456  /// ## Example
457  /// ```cpp
458  /// variant<int, std::string> v{
459  /// std::in_place_type<std::string>,
460  /// 5, 'a'};
461  ///
462  /// assert(holds_alternative<std::string>(v));
463  ///
464  /// assert(v.index() == 1);
465  ///
466  /// assert(get<1>(v) == "aaaaa");
467  /// ```
468  template <typename U, typename... Args>
469 #ifndef DOXYGEN
470  requires(detail::is_unique_v<U, T...>)
471  explicit(sizeof...(Args) == 0)
472 #else
474 #endif
475  // NOLINTNEXTLINE(hicpp-explicit-conversions)
476  constexpr variant([[maybe_unused]] std::in_place_type_t<U> inplace, Args&&... args)
477  : detail::variant_impl<void, T...>(std::in_place_index<detail::index_of_v<U, T...>>,
478  std::forward<Args>(args)...) {
479  }
480 
481  /// @brief Type emplacement constructor with `std::initializer_list`
482  ///
483  /// @details
484  /// A new @ref variant is initialized such that it contains a newly
485  /// constructed instance of the alternative with the specified type.
486  /// The arguments following `inplace` are forwarded directory to the
487  /// constructor of the alternative type.
488  ///
489  /// This constructor only participates in overload resolution if the
490  /// alternative type, `U`, is unique among all alternatives of the @ref
491  /// variant. That is, `variant<A, B, A>`, cannot use this constructor to
492  /// initialize an alternative of type `A`, but it could use this
493  /// constructor to initialize the alternative of type `B`. This constraint
494  /// is imposed to prevent ambiguity to the reader. Use the index based
495  /// emplacement constructor instead to initialize the alternative of type
496  /// `A`.
497  ///
498  /// ## Example
499  /// ```cpp
500  /// variant<int, std::vector<int>> v{
501  /// std::in_place_type<std::vector<int>>,
502  /// {1, 2, 3, 4, 5}};
503  ///
504  /// assert(holds_alternative<std::vector<int>>(v));
505  ///
506  /// assert(v.index() == 1);
507  ///
508  /// assert(get<1>(v).size() == 5);
509  /// ```
510  template <typename U, typename V, typename... Args>
511 #ifndef DOXYGEN
512  requires(detail::is_unique_v<U, T...>)
513 #endif
514  constexpr variant([[maybe_unused]] std::in_place_type_t<U> inplace,
515  std::initializer_list<V> init,
516  Args&&... args)
517  : detail::variant_impl<void, T...>(std::in_place_index<detail::index_of_v<U, T...>>,
518  init,
519  std::forward<Args>(args)...) {
520  }
521 
522  /// @brief Forwarding constructor
523  ///
524  /// @details
525  /// A new @ref variant is initialized such that an alternative is
526  /// constructed in place with the provided value as the constructor
527  /// argument.
528  ///
529  /// To avoid ambiguity to the reader, this constructor only participates
530  /// in overload resolution when there is only one alternative that could
531  /// possibly be constructed from the value.
532  ///
533  /// This constructor is `explicit` if the value is not implicitly
534  /// convertible to the target alternative type.
535  ///
536  /// This constructor should be avoided in generic code, because some @ref
537  /// variant instantiations will have distinct types while others will not.
538  /// Prefer the emplacement constructors.
539  ///
540  /// ## Example
541  /// ```cpp
542  /// variant<void, int> v{42};
543  ///
544  /// assert(v.index() == 1);
545  ///
546  /// assert(get<1>(v) == 42);
547  /// ```
548  ///
549  /// @param value The value that is used to construct the alternative
550  template <typename U>
551 #ifndef DOXYGEN
552  requires(!std::is_same_v<std::remove_cvref_t<U>, variant<T...>> &&
555 #else
557 #endif
558  // NOLINTNEXTLINE(hicpp-explicit-conversions)
559  constexpr variant(U&& value)
560  : variant(emplace_construct_t<0>{}, std::forward<U>(value)) {
561  }
562 
563  /// @brief Forwarding constructor with initializer list
564  ///
565  /// @details
566  /// A new @ref variant is initialized such that an alternative is
567  /// constructed in place with the provided `std::initializer_list`
568  /// as the constructor argument.
569  ///
570  /// To avoid ambiguity to the reader, this constructor only participates
571  /// in overload resulotion when there is only one alternative that could
572  /// possible be constructed from the initializer list.
573  ///
574  /// This constructor is `explicit` if the `std::initializer_list` is not
575  /// implicitly convertible to the target alternative type.
576  ///
577  /// This constructor should be avoided in generic code, because some @ref
578  /// variant instantiations will have distinct types while others will not.
579  /// Prefer the emplacement constructors.
580  ///
581  /// ## Example
582  /// ```cpp
583  /// variant<void, std::vector<int>> v({1, 2, 3, 4, 5});
584  ///
585  /// assert(v.index() == 1);
586  ///
587  /// assert(get<1>(v).size() == 5);
588  /// ```
589  ///
590  /// @param init The `std::initializer_list` that is used to construct the
591  /// alternative
592  template <typename U>
593 #ifndef DOXYGEN
596 #else
598 #endif
599  constexpr variant(std::initializer_list<U> init)
600  : variant(emplace_construct_t<0>{}, init) {
601  }
602 
603  /// @brief Destructor
604  ///
605  /// @details
606  /// The contained alternative of the @ref variant will is destroyed in
607  /// place.
608  ///
609  /// The destructor is `noexcept` if all alternative types are nothrow
610  /// destructible.
611  constexpr ~variant()
612 #ifndef DOXYGEN
613  noexcept((true && ... && detail::traits<T>::is_nothrow_destructible)) = default;
614 #else
615  CONDITIONALLY_NOEXCEPT;
616 #endif
617 
618  /// @brief Copy assignment operator
619  ///
620  /// @details
621  /// Copy assignment of a @ref variant can take one of two possible code
622  /// paths.
623  ///
624  /// If the source and destination @ref variant hold the same alternative
625  /// (same index), the alternative value is copied via copy assignment.
626  ///
627  /// Otherwise, if the source and destination hold different alternatives
628  /// (different indices, but possibly the same type), the alternative of
629  /// the destination @ref variant is destroyed in place, and the new
630  /// alternative is copy constructed.
631  ///
632  /// All alternatives *must* be both copy assignable and copy constructible
633  /// for this function to participate in overload resolution.
634  ///
635  /// ## Example
636  /// ```cpp
637  /// variant<int, bool> v1{std::in_place_index<0>, 42};
638  ///
639  /// variant<int, bool> v2{std::in_place_index<1>, true};
640  ///
641  /// v1 = v2;
642  ///
643  /// assert(holds_alternative<bool>(v1));
644  ///
645  /// assert(v1.index() == 1);
646  ///
647  /// assert(get<1>(v1) == true);
648  /// ```
649  constexpr variant& operator=(const variant& rhs)
650 #ifndef DOXYGEN
651  requires(true && ... &&
654  = default;
655 #else
656  ;
657 #endif
658 
659  /// @brief Move assignment operator
660  ///
661  /// @details
662  /// Move assignment of a @ref variant can take one of two possible code
663  /// paths.
664  ///
665  /// If the source and destination @ref variant hold the same alternative
666  /// (same index), the alternative value is moved from the source to the
667  /// destination via move assignment.
668  ///
669  /// Otherwise, if the source and destination hold different alternatives
670  /// (different indices, but possibly the same type), the alternative of the
671  /// destination @ref variant is destroyed in place, and the new alternative
672  /// is move constructed.
673  ///
674  /// The source @ref variant will still contain the same alternative, but
675  /// the value of the alternative depends on the move assignment or move
676  /// constructor of the alternative's type. In general, moved values are
677  /// said to be in a valid, but unspecified, state.
678  ///
679  /// All alternatives *must* be both move assignable and move constructible
680  /// for this function to participate in overload resolution.
681  ///
682  /// ## Example
683  /// ```cpp
684  /// variant<int, bool> v1{std::in_place_index<0>, 42};
685  ///
686  /// variant<int, bool> v2{std::in_place_index<1>, true};
687  ///
688  /// v1 = std::move(v2);
689  ///
690  /// assert(holds_alternative<bool>(v1));
691  ///
692  /// assert(v1.index() == 1);
693  ///
694  /// assert(get<1>(v1) == true);
695  /// ```
696  constexpr variant& operator=(variant&& rhs)
697 #ifndef DOXYGEN
698  noexcept((true && ... &&
702  requires(true && ... &&
705  = default;
706 #else
707  ;
708 #endif
709 
710  private:
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<
714  U>) {
715  if (index() == IDX) {
716  if constexpr (!std::is_void_v<detail::select_t<IDX, T...>>) {
717  data_().template get<IDX>() = std::forward<U>(value);
718  }
719  } else {
720  data_().template emplace<IDX>(std::forward<U>(value));
721  }
722  } else {
723  assign_value<IDX + 1>(std::forward<U>(value));
724  }
725  }
726 
727  public:
728  /// @brief Forwarding assignment operator
729  ///
730  /// @details
731  /// This function assigns a value directly to an alternative. If the @ref
732  /// variant already contains the target alternative, the value is assigned
733  /// using the alternative type's assignemnt operator. Otherwise, the target
734  /// alternative is constructed with the value.
735  ///
736  /// To avoid ambiguity to the reader, this function only participates in
737  /// overload resolution when there is only one alternative that could
738  /// possibly be assigned from the value.
739  ///
740  /// This operator should be avoided in generic code, because some @ref
741  /// variant instantiations will have distinct types while others will not.
742  ///
743  /// ## Example
744  /// ```cpp
745  /// variant<void, int> v{};
746  ///
747  /// v = 42;
748  ///
749  /// assert(v.index() == 1);
750  ///
751  /// assert(get<1>(v) == 42);
752  /// ```
753  ///
754  /// @param rhs The value to be assigned to the alternative
755  template <typename U>
756 #ifndef DOXYGEN
757  requires(!std::is_same_v<std::remove_cvref_t<U>, variant> &&
759 #endif
760  constexpr variant& operator=(U&& rhs) {
761  assign_value<0>(std::forward<U>(rhs));
762  return *this;
763  }
764 
765  /// @brief Forwarding assignment operator with initializer list
766  ///
767  /// @details
768  /// This function assigns a `std::initializer_list` directoy to an
769  /// alternative. If the @ref variant already contains the target
770  /// alternative, the `std::initializer_list` is assigned uting the
771  /// alternative type's assignment operator. Otherwise, the target
772  /// alternative is constructed with the `std::initializer_list`.
773  ///
774  /// To avoid ambiguity to the reader, this function only participates in
775  /// overload resolution when there is only one alternative that could
776  /// possibly be assigned from the `std::initializer_list`.
777  ///
778  /// This opreator should be avoided in generic code, because some @ref
779  /// variant instantiations will have distinct types while others will not.
780  ///
781  /// ## Example
782  /// ```cpp
783  /// variant<void, std::vector<int>> v{};
784  ///
785  /// v = {1, 2, 3, 4, 5};
786  ///
787  /// assert(v.index() == 1);
788  ///
789  /// assert(get<1>(v).size() == 5);
790  /// ```
791  ///
792  /// @param rhs The `std::initializer_list` to be assigned to the
793  /// alternative
794  template <typename U>
795 #ifndef DOXYGEN
797 #endif
798  constexpr variant& operator=(std::initializer_list<U> rhs) {
799  assign_value<0>(rhs);
800  return *this;
801  }
802 
803  /// @brief Gets the index of the contained alternative
804  ///
805  /// @details
806  /// The set of alternatives of a @ref variant has a zero-based index based
807  /// on the order in which they are specified in the @ref variant template
808  /// arguments.
809  ///
810  /// This index is the normalized discriminant of the @ref variant. The
811  /// discriminant may be represented differently internally, depending on
812  /// the alternative types, so this function normalizes the discriminant by
813  /// converting it to a zero-based index in order to provide a common
814  /// interface for all @ref variant instantiations.
815  ///
816  /// ## Example
817  /// ```cpp
818  /// variant<int, bool, float&, std::string, void> v{
819  /// std::in_place_index<3>, "hello"};
820  ///
821  /// assert(v.index() == 3);
822  /// ```
823  ///
824  /// @return The index of the contained alternative.
825  [[nodiscard]] constexpr size_t index() const noexcept { return data_().index(); }
826 
827  /// @brief Constructs a new alternative in place by index
828  ///
829  /// @details
830  /// This function destroys the alternative that the @ref variant contains
831  /// before the call, and constructs a new alternative with the specified
832  /// index in place.
833  ///
834  /// ## Example
835  /// ```cpp
836  /// variant<int, std::string> v;
837  ///
838  /// v.emplace<1>(5, 'a');
839  ///
840  /// assert(holds_alternative<std::string>(v));
841  ///
842  /// assert(v.index() == 1);
843  ///
844  /// assert(get<1>(v) == "aaaaa");
845  /// ```
846  ///
847  /// @param args Constructor arguments forwarded to the new alternative
848  /// @return A reference to the new alternative, if applicable
849  template <size_t I, typename... Args>
850  constexpr
851 #ifndef DOXYGEN
852  typename detail::traits<detail::select_t<I, T...>>::reference
853 #else
854  REFERENCE
855 #endif
856  emplace(Args&&... args) {
857  data_().template emplace<I>(std::forward<Args>(args)...);
858  return data_().template get<I>();
859  }
860 
861  /// @brief Constructs a new alternative in place by index
862  ///
863  /// @details
864  /// This function destroys the alternative that the @ref variant contains
865  /// before the call, and constructs a new alternative with the specified
866  /// index in place.
867  ///
868  /// ## Example
869  /// ```cpp
870  /// variant<int, std::vector<int>> v;
871  ///
872  /// v.emplace<1>({1, 2, 3, 4, 5});
873  ///
874  /// assert(holds_alternative<std::vector<int>>(v));
875  ///
876  /// assert(v.index() == 1);
877  ///
878  /// assert(get<1>(v).size() == 5);
879  /// ```
880  ///
881  /// @param ilist Initializer list forward to the new alternative
882  /// @param args Constructor arguments forwarded to the new alternative
883  /// @return A reference to the new alternative, if applicable
884  template <size_t I, typename U, typename... Args>
885  constexpr
886 #ifndef DOXYGEN
887  typename detail::traits<detail::select_t<I, T...>>::reference
888 #else
889  REFERENCE
890 #endif
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>();
894  }
895 
896  /// @brief Constructs a new alternative in place by type
897  ///
898  /// @details
899  /// This function destroy the alternative that the @ref variant contains
900  /// before the call, and constructs a new alternative with the specified
901  /// type in place.
902  ///
903  /// This function only participates in overload resolution if the type,
904  /// `U`, is unique among all the alternative types of the @ref variant.
905  /// That is, `variant<A, B, A>` cannot use this function to emplace an
906  /// alternative of type `A`, but it can use this function to emplace an
907  /// alternative of type `B`.
908  ///
909  /// ## Example
910  /// ```cpp
911  /// variant<int, std::string> v;
912  ///
913  /// v.emplace<std::string>(5, 'a');
914  ///
915  /// assert(holds_alternative<std::string>(v));
916  ///
917  /// assert(v.index() == 1);
918  ///
919  /// assert(get<1>(v) == "aaaaa");
920  /// ```
921  ///
922  /// @param args Constructor arguments forwarded to the new alternative
923  /// @return A reference to the new alternative, if applicable
924  template <typename U, typename... Args>
925 #ifndef DOXYGEN
926  requires(detail::is_unique_v<U, T...>)
927 #endif
928  constexpr
929 #ifndef DOXYGEN
930  typename detail::traits<U>::reference
931 #else
932  REFERENCE
933 #endif
934  emplace(Args&&... 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...>>();
937  }
938 
939  /// @brief Constructs a new alternative in place by type
940  ///
941  /// @details
942  /// This function destroy the alternative that the @ref variant contains
943  /// before the call, and constructs a new alternative with the specified
944  /// type in place.
945  ///
946  /// This function only participates in overload resolution if the type,
947  /// `U`, is unique among all the alternative types of the @ref variant.
948  /// That is, `variant<A, B, A>` cannot use this function to emplace an
949  /// alternative of type `A`, but it can use this function to emplace an
950  /// alternative of type `B`.
951  ///
952  /// ## Example
953  /// ```cpp
954  /// variant<int, std::vector<int>> v;
955  ///
956  /// v.emplace<std::vector<int>>({1, 2, 3, 4, 5});
957  ///
958  /// assert(holds_alternative<std::vector<int>>(v));
959  ///
960  /// assert(v.index() == 1);
961  ///
962  /// assert(get<1>(v).size() == 5);
963  /// ```
964  ///
965  /// @param ilist Initializer list forward to the new alternative
966  /// @param args Constructor arguments forwarded to the new alternative
967  /// @return A reference to the new alternative, if applicable
968  template <typename U, typename V, typename... Args>
969 #ifndef DOXYGEN
970  requires(detail::is_unique_v<U, T...>)
971 #endif
972  constexpr
973 #ifndef DOXYGEN
974  typename detail::traits<U>::reference
975 #else
976  REFERENCE
977 #endif
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...>>();
982  }
983 
984  /// @brief Alternative access operator by index
985  ///
986  /// @details
987  /// This function allows accessing alternatives by index using the square
988  /// bracket operator. Because the index must be a compile time value,
989  /// instead of passing the index directly, the index is provided as an
990  /// instance of @ref index_t.
991  ///
992  /// This operator is unchecked and does not throw an exception. Passing an
993  /// index that does not correspond to the currently contained alternative
994  /// results in undefined behavior.
995  ///
996  /// ## Example
997  /// ```cpp
998  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
999  ///
1000  /// assert(v[index<1>] == 42);
1001  ///
1002  /// v[index<1>] = 24;
1003  ///
1004  /// assert(get<1>(v) == 24);
1005  /// ```
1006  ///
1007  /// @param index A tag value that communicates a compile time index
1008  /// @return A reference to the accessed alternative, if applicable
1009  template <size_t I>
1010  [[nodiscard]] constexpr
1011 #ifndef DOXYGEN
1012  typename detail::traits<detail::select_t<I, T...>>::reference
1013 #else
1014  REFERENCE
1015 #endif
1016  operator[]([[maybe_unused]] index_t<I> index) & noexcept {
1017  return data_().template get<I>();
1018  }
1019 
1020  /// @brief Alternative access operator by index
1021  ///
1022  /// @details
1023  /// This function allows accessing alternatives by index using the square
1024  /// bracket operator. Because the index must be a compile time value,
1025  /// instead of passing the index directly, the index is provided as an
1026  /// instance of @ref index_t.
1027  ///
1028  /// This operator is unchecked and does not throw an exception. Passing an
1029  /// index that does not correspond to the currently contained alternative
1030  /// results in undefined behavior.
1031  ///
1032  /// ## Example
1033  /// ```cpp
1034  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1035  ///
1036  /// assert(v[index<1>] == 42);
1037  ///
1038  /// v[index<1>] = 24;
1039  ///
1040  /// assert(get<1>(v) == 24);
1041  /// ```
1042  ///
1043  /// @param index A tag value that communicates a compile time index
1044  /// @return A reference to the accessed alternative, if applicable
1045  template <size_t I>
1046  [[nodiscard]] constexpr
1047 #ifndef DOXYGEN
1048  typename detail::traits<detail::select_t<I, T...>>::const_reference
1049 #else
1051 #endif
1052  operator[]([[maybe_unused]] index_t<I> index) const& noexcept {
1053  return data_().template get<I>();
1054  }
1055 
1056  /// @brief Alternative access operator by index
1057  ///
1058  /// @details
1059  /// This function allows accessing alternatives by index using the square
1060  /// bracket operator. Because the index must be a compile time value,
1061  /// instead of passing the index directly, the index is provided as an
1062  /// instance of @ref index_t.
1063  ///
1064  /// This operator is unchecked and does not throw an exception. Passing an
1065  /// index that does not correspond to the currently contained alternative
1066  /// results in undefined behavior.
1067  ///
1068  /// ## Example
1069  /// ```cpp
1070  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1071  ///
1072  /// assert(v[index<1>] == 42);
1073  ///
1074  /// v[index<1>] = 24;
1075  ///
1076  /// assert(get<1>(v) == 24);
1077  /// ```
1078  ///
1079  /// @param index A tag value that communicates a compile time index
1080  /// @return The accessed alternative value, if applicable
1081  template <size_t I>
1082  [[nodiscard]] constexpr
1083 #ifndef DOXYGEN
1084  typename detail::traits<detail::select_t<I, T...>>::rvalue_reference
1085 #else
1087 #endif
1088  operator[]([[maybe_unused]] index_t<I> index) && {
1089  return std::move(data_()).template get<I>();
1090  }
1091 
1092  /// @brief Alternative access operator by index
1093  ///
1094  /// @details
1095  /// This function allows accessing alternatives by index using the square
1096  /// bracket operator. Because the index must be a compile time value,
1097  /// instead of passing the index directly, the index is provided as an
1098  /// instance of @ref index_t.
1099  ///
1100  /// This operator is unchecked and does not throw an exception. Passing an
1101  /// index that does not correspond to the currently contained alternative
1102  /// results in undefined behavior.
1103  ///
1104  /// ## Example
1105  /// ```cpp
1106  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1107  ///
1108  /// assert(v[index<1>] == 42);
1109  ///
1110  /// v[index<1>] = 24;
1111  ///
1112  /// assert(get<1>(v) == 24);
1113  /// ```
1114  ///
1115  /// @param index A tag value that communicates a compile time index
1116  /// @return The accessed alternative value, if applicable
1117  template <size_t I>
1118  [[nodiscard]] constexpr
1119 #ifndef DOXYGEN
1120  typename detail::traits<detail::select_t<I, T...>>::const_rvalue_reference
1121 #else
1123 #endif
1124  operator[]([[maybe_unused]] index_t<I> index) const&& {
1125  return std::move(data_()).template get<I>();
1126  }
1127 
1128  /// @brief Alternative access operator by type
1129  ///
1130  /// @details
1131  /// This function allows accessing alternatives by type using the square
1132  /// bracket operator. Because the type must be a compile time value,
1133  /// the type is provided as an instance of @ref type_t.
1134  ///
1135  /// This operator is unchecked and does not throw an exception. Passing a
1136  /// type that does not correspond to the currently contained alternative
1137  /// results in undefined behavior.
1138  ///
1139  /// This function only participates in overload resolution if the type is
1140  /// unique across all alternative types of the @ref variant. That is,
1141  /// `variant<A, B, A>` cannot use this function to access an alternative
1142  /// of type `A`, but it can use this fucntion to access an alternative of
1143  /// type `B`.
1144  ///
1145  /// ## Example
1146  /// ```cpp
1147  /// variant<bool, int, void> v{std::in_place_type<int>, 42};
1148  ///
1149  /// assert(v[type<int>] == 42);
1150  ///
1151  /// v[type<int>] = 24;
1152  ///
1153  /// assert(get<int>(v) == 24);
1154  /// ```
1155  ///
1156  /// @param index A tag value that communicates a compile time index
1157  /// @return A reference to the accessed alternative, if applicable
1158  template <typename U>
1159 #ifndef DOXYGEN
1160  requires detail::is_unique_v<U, T...>
1161 #endif
1162  [[nodiscard]] constexpr
1163 #ifndef DOXYGEN
1164  typename detail::traits<U>::reference
1165 #else
1166  REFERENCE
1167 #endif
1168  operator[]([[maybe_unused]] type_t<U> type) & noexcept {
1169  return this->operator[](sumty::index<detail::index_of_v<U, T...>>);
1170  }
1171 
1172  /// @brief Alternative access operator by type
1173  ///
1174  /// @details
1175  /// This function allows accessing alternatives by type using the square
1176  /// bracket operator. Because the type must be a compile time value,
1177  /// the type is provided as an instance of @ref type_t.
1178  ///
1179  /// This operator is unchecked and does not throw an exception. Passing a
1180  /// type that does not correspond to the currently contained alternative
1181  /// results in undefined behavior.
1182  ///
1183  /// This function only participates in overload resolution if the type is
1184  /// unique across all alternative types of the @ref variant. That is,
1185  /// `variant<A, B, A>` cannot use this function to access an alternative
1186  /// of type `A`, but it can use this fucntion to access an alternative of
1187  /// type `B`.
1188  ///
1189  /// ## Example
1190  /// ```cpp
1191  /// variant<bool, int, void> v{std::in_place_type<int>, 42};
1192  ///
1193  /// assert(v[type<int>] == 42);
1194  ///
1195  /// v[type<int>] = 24;
1196  ///
1197  /// assert(get<int>(v) == 24);
1198  /// ```
1199  ///
1200  /// @param index A tag value that communicates a compile time index
1201  /// @return A reference to the accessed alternative, if applicable
1202  template <typename U>
1203 #ifndef DOXYGEN
1204  requires detail::is_unique_v<U, T...>
1205 #endif
1206  [[nodiscard]] constexpr
1207 #ifndef DOXYGEN
1208  typename detail::traits<U>::const_reference
1209 #else
1211 #endif
1212  operator[]([[maybe_unused]] type_t<U> type) const& noexcept {
1213  return this->operator[](sumty::index<detail::index_of_v<U, T...>>);
1214  }
1215 
1216  /// @brief Alternative access operator by type
1217  ///
1218  /// @details
1219  /// This function allows accessing alternatives by type using the square
1220  /// bracket operator. Because the type must be a compile time value,
1221  /// the type is provided as an instance of @ref type_t.
1222  ///
1223  /// This operator is unchecked and does not throw an exception. Passing a
1224  /// type that does not correspond to the currently contained alternative
1225  /// results in undefined behavior.
1226  ///
1227  /// This function only participates in overload resolution if the type is
1228  /// unique across all alternative types of the @ref variant. That is,
1229  /// `variant<A, B, A>` cannot use this function to access an alternative
1230  /// of type `A`, but it can use this fucntion to access an alternative of
1231  /// type `B`.
1232  ///
1233  /// ## Example
1234  /// ```cpp
1235  /// variant<bool, int, void> v{std::in_place_type<int>, 42};
1236  ///
1237  /// assert(v[type<int>] == 42);
1238  ///
1239  /// v[type<int>] = 24;
1240  ///
1241  /// assert(get<int>(v) == 24);
1242  /// ```
1243  ///
1244  /// @param index A tag value that communicates a compile time index
1245  /// @return The accessed alternative value, if applicable
1246  template <typename U>
1247 #ifndef DOXYGEN
1248  requires detail::is_unique_v<U, T...>
1249 #endif
1250  [[nodiscard]] constexpr
1251 #ifndef DOXYGEN
1252  typename detail::traits<U>::rvalue_reference
1253 #else
1255 #endif
1256  operator[]([[maybe_unused]] type_t<U> type) && {
1257  return std::move(*this).operator[](sumty::index<detail::index_of_v<U, T...>>);
1258  }
1259 
1260  /// @brief Alternative access operator by type
1261  ///
1262  /// @details
1263  /// This function allows accessing alternatives by type using the square
1264  /// bracket operator. Because the type must be a compile time value,
1265  /// the type is provided as an instance of @ref type_t.
1266  ///
1267  /// This operator is unchecked and does not throw an exception. Passing a
1268  /// type that does not correspond to the currently contained alternative
1269  /// results in undefined behavior.
1270  ///
1271  /// This function only participates in overload resolution if the type is
1272  /// unique across all alternative types of the @ref variant. That is,
1273  /// `variant<A, B, A>` cannot use this function to access an alternative
1274  /// of type `A`, but it can use this fucntion to access an alternative of
1275  /// type `B`.
1276  ///
1277  /// ## Example
1278  /// ```cpp
1279  /// variant<bool, int, void> v{std::in_place_type<int>, 42};
1280  ///
1281  /// assert(v[type<int>] == 42);
1282  ///
1283  /// v[type<int>] = 24;
1284  ///
1285  /// assert(get<int>(v) == 24);
1286  /// ```
1287  ///
1288  /// @param index A tag value that communicates a compile time index
1289  /// @return The accessed alternative value, if applicable
1290  template <typename U>
1291 #ifndef DOXYGEN
1292  requires detail::is_unique_v<U, T...>
1293 #endif
1294  [[nodiscard]] constexpr
1295 #ifndef DOXYGEN
1296  typename detail::traits<U>::const_rvalue_reference
1297 #else
1299 #endif
1300  operator[]([[maybe_unused]] type_t<U> type) const&& {
1301  return std::move(*this).operator[](sumty::index<detail::index_of_v<U, T...>>);
1302  }
1303 
1304  /// @brief Gets an alternative by index
1305  ///
1306  /// @details
1307  /// This function allows accessing alternatives by index, which is provided
1308  /// as a template argument.
1309  ///
1310  /// ## Example
1311  /// ```cpp
1312  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1313  ///
1314  /// assert(v.get<1>() == 42);
1315  ///
1316  /// v.get<1>() = 24;
1317  ///
1318  /// assert(get<int>(v) == 24);
1319  /// ```
1320  ///
1321  /// @tparam I The index of the alternative to access.
1322  ///
1323  /// @return A reference to the accessed alternative, if applicable.
1324  ///
1325  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1326  /// the alternative with the corresponding index.
1327  template <size_t I>
1328  [[nodiscard]] constexpr
1329 #ifndef DOXYGEN
1330  typename detail::traits<detail::select_t<I, T...>>::reference
1331 #else
1332  REFERENCE
1333 #endif
1334  get() & {
1335  if (index() != I) { throw bad_variant_access(); }
1336  return data_().template get<I>();
1337  }
1338 
1339  /// @brief Gets an alternative by index
1340  ///
1341  /// @details
1342  /// This function allows accessing alternatives by index, which is provided
1343  /// as a template argument.
1344  ///
1345  /// ## Example
1346  /// ```cpp
1347  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1348  ///
1349  /// assert(v.get<1>() == 42);
1350  ///
1351  /// v.get<1>() = 24;
1352  ///
1353  /// assert(get<int>(v) == 24);
1354  /// ```
1355  ///
1356  /// @tparam I The index of the alternative to access.
1357  ///
1358  /// @return A reference to the accessed alternative, if applicable.
1359  ///
1360  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1361  /// the alternative with the corresponding index.
1362  template <size_t I>
1363  [[nodiscard]] constexpr
1364 #ifndef DOXYGEN
1365  typename detail::traits<detail::select_t<I, T...>>::const_reference
1366 #else
1368 #endif
1369  get() const& {
1370  if (index() != I) { throw bad_variant_access(); }
1371  return data_().template get<I>();
1372  }
1373 
1374  /// @brief Gets an alternative by index
1375  ///
1376  /// @details
1377  /// This function allows accessing alternatives by index, which is provided
1378  /// as a template argument.
1379  ///
1380  /// ## Example
1381  /// ```cpp
1382  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1383  ///
1384  /// assert(v.get<1>() == 42);
1385  ///
1386  /// v.get<1>() = 24;
1387  ///
1388  /// assert(get<int>(v) == 24);
1389  /// ```
1390  ///
1391  /// @tparam I The index of the alternative to access.
1392  ///
1393  /// @return The accessed alternative value, if applicable.
1394  ///
1395  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1396  /// the alternative with the corresponding index.
1397  template <size_t I>
1398  [[nodiscard]] constexpr
1399 #ifndef DOXYGEN
1400  typename detail::traits<detail::select_t<I, T...>>::rvalue_reference
1401 #else
1403 #endif
1404  get() && {
1405  if (index() != I) { throw bad_variant_access(); }
1406  return std::move(data_()).template get<I>();
1407  }
1408 
1409  /// @brief Gets an alternative by index
1410  ///
1411  /// @details
1412  /// This function allows accessing alternatives by index, which is provided
1413  /// as a template argument.
1414  ///
1415  /// ## Example
1416  /// ```cpp
1417  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1418  ///
1419  /// assert(v.get<1>() == 42);
1420  ///
1421  /// v.get<1>() = 24;
1422  ///
1423  /// assert(get<int>(v) == 24);
1424  /// ```
1425  ///
1426  /// @tparam I The index of the alternative to access.
1427  ///
1428  /// @return The accessed alternative value, if applicable.
1429  ///
1430  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1431  /// the alternative with the corresponding index.
1432  template <size_t I>
1433  [[nodiscard]] constexpr
1434 #ifndef DOXYGEN
1435  typename detail::traits<detail::select_t<I, T...>>::const_rvalue_reference
1436 #else
1438 #endif
1439  get() const&& {
1440  if (index() != I) { throw bad_variant_access(); }
1441  return std::move(data_()).template get<I>();
1442  }
1443 
1444  /// @brief Gets an alternative by type
1445  ///
1446  /// @details
1447  /// This function allows accessing alternatives by type, which is provided
1448  /// as a template argument.
1449  ///
1450  /// This function only participates in overload resolution if the type is
1451  /// unique across all alternative types of the @ref variant. That is,
1452  /// `variant<A, B, A>` cannot use this function to access an alternative
1453  /// of type `A`, but it can use this fucntion to access an alternative of
1454  /// type `B`.
1455  ///
1456  /// ## Example
1457  /// ```cpp
1458  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1459  ///
1460  /// assert(v.get<int>() == 42);
1461  ///
1462  /// v.get<int>() = 24;
1463  ///
1464  /// assert(get<int>(v) == 24);
1465  /// ```
1466  ///
1467  /// @tparam U The type of the alternative to access.
1468  ///
1469  /// @return A reference to the accessed alternative, if applicable.
1470  ///
1471  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1472  /// the alternative with the corresponding type.
1473  template <typename U>
1474 #ifndef DOXYGEN
1475  requires detail::is_unique_v<U, T...>
1476 #endif
1477  [[nodiscard]] constexpr
1478 #ifndef DOXYGEN
1479  typename detail::traits<U>::reference
1480 #else
1481  REFERENCE
1482 #endif
1483  get() & {
1484  return this->template get<detail::index_of_v<U, T...>>();
1485  }
1486 
1487  /// @brief Gets an alternative by type
1488  ///
1489  /// @details
1490  /// This function allows accessing alternatives by type, which is provided
1491  /// as a template argument.
1492  ///
1493  /// This function only participates in overload resolution if the type is
1494  /// unique across all alternative types of the @ref variant. That is,
1495  /// `variant<A, B, A>` cannot use this function to access an alternative
1496  /// of type `A`, but it can use this fucntion to access an alternative of
1497  /// type `B`.
1498  ///
1499  /// ## Example
1500  /// ```cpp
1501  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1502  ///
1503  /// assert(v.get<int>() == 42);
1504  ///
1505  /// v.get<int>() = 24;
1506  ///
1507  /// assert(get<int>(v) == 24);
1508  /// ```
1509  ///
1510  /// @tparam U The type of the alternative to access.
1511  ///
1512  /// @return A reference to the accessed alternative, if applicable.
1513  ///
1514  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1515  /// the alternative with the corresponding type.
1516  template <typename U>
1517 #ifndef DOXYGEN
1518  requires detail::is_unique_v<U, T...>
1519 #endif
1520  [[nodiscard]] constexpr
1521 #ifndef DOXYGEN
1522  typename detail::traits<U>::const_reference
1523 #else
1525 #endif
1526  get() const& {
1527  return this->template get<detail::index_of_v<U, T...>>();
1528  }
1529 
1530  /// @brief Gets an alternative by type
1531  ///
1532  /// @details
1533  /// This function allows accessing alternatives by type, which is provided
1534  /// as a template argument.
1535  ///
1536  /// This function only participates in overload resolution if the type is
1537  /// unique across all alternative types of the @ref variant. That is,
1538  /// `variant<A, B, A>` cannot use this function to access an alternative
1539  /// of type `A`, but it can use this fucntion to access an alternative of
1540  /// type `B`.
1541  ///
1542  /// ## Example
1543  /// ```cpp
1544  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1545  ///
1546  /// assert(v.get<int>() == 42);
1547  ///
1548  /// v.get<int>() = 24;
1549  ///
1550  /// assert(get<int>(v) == 24);
1551  /// ```
1552  ///
1553  /// @tparam U The type of the alternative to access.
1554  ///
1555  /// @return The accessed alternative value, if applicable.
1556  ///
1557  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1558  /// the alternative with the corresponding type.
1559  template <typename U>
1560 #ifndef DOXYGEN
1561  requires detail::is_unique_v<U, T...>
1562 #endif
1563  [[nodiscard]] constexpr
1564 #ifndef DOXYGEN
1565  typename detail::traits<U>::rvalue_reference
1566 #else
1568 #endif
1569  get() && {
1570  return std::move(*this).template get<detail::index_of_v<U, T...>>();
1571  }
1572 
1573  /// @brief Gets an alternative by type
1574  ///
1575  /// @details
1576  /// This function allows accessing alternatives by type, which is
1577  /// provided as a template argument.
1578  ///
1579  /// This function only participates in overload resolution if the type is
1580  /// unique across all alternative types of the @ref variant. That is,
1581  /// `variant<A, B, A>` cannot use this function to access an alternative
1582  /// of type `A`, but it can use this fucntion to access an alternative of
1583  /// type `B`.
1584  ///
1585  /// ## Example
1586  /// ```cpp
1587  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1588  ///
1589  /// assert(v.get<int>() == 42);
1590  ///
1591  /// v.get<int>() = 24;
1592  ///
1593  /// assert(get<int>(v) == 24);
1594  /// ```
1595  ///
1596  /// @tparam U The type of the alternative to access.
1597  ///
1598  /// @return The accessed alternative value, if applicable.
1599  ///
1600  /// @throws bad_variant_access Thrown if the @ref variant does not contain
1601  /// the alternative with the corresponding type.
1602  template <typename U>
1603 #ifndef DOXYGEN
1604  requires detail::is_unique_v<U, T...>
1605 #endif
1606  [[nodiscard]] constexpr
1607 #ifndef DOXYGEN
1608  typename detail::traits<U>::const_rvalue_reference
1609 #else
1611 #endif
1612  get() const&& {
1613  return std::move(*this).template get<detail::index_of_v<U, T...>>();
1614  }
1615 
1616  /// @brief Gets an alternative pointer by index if the @ref variant holds it
1617  ///
1618  /// @details
1619  /// This functions tries to access an alternative by index. If the @ref
1620  /// variant contains the alternative, this function returns a pointer to
1621  /// the alternative, if applicable. If the @ref variant does not contain
1622  /// the alternative, this function returns null. In the case where the
1623  /// alternative is of type `void`, this function does nothing.
1624  ///
1625  /// ## Example
1626  /// ```cpp
1627  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1628  ///
1629  /// assert(*v.get_if<1>() == 42);
1630  ///
1631  /// *v.get_if<1>() = 24;
1632  ///
1633  /// assert(*v.get_if<1>() == 24);
1634  ///
1635  /// assert(v.get_if<0>() == nullptr);
1636  /// ```
1637  ///
1638  /// @tparam I The index of the alternative to access.
1639  ///
1640  /// @return A pointer to the accessed alternative, if applicable, or null
1641  template <size_t I>
1642  [[nodiscard]] constexpr
1643 #ifndef DOXYGEN
1644  typename detail::traits<detail::select_t<I, T...>>::pointer
1645 #else
1646  POINTER
1647 #endif
1648  get_if() noexcept {
1649  using ptr_t = typename detail::traits<detail::select_t<I, T...>>::pointer;
1650  if constexpr (!std::is_void_v<ptr_t>) {
1651  ptr_t ret;
1652  if (index() == I) {
1653  ret = &data_().template get<I>();
1654  } else {
1655  ret = nullptr;
1656  }
1657  return ret;
1658  } else {
1659  return;
1660  }
1661  }
1662 
1663  /// @brief Gets an alternative pointer by index if the @ref variant holds it
1664  ///
1665  /// @details
1666  /// This functions tries to access an alternative by index. If the @ref
1667  /// variant contains the alternative, this function returns a pointer to
1668  /// the alternative, if applicable. If the @ref variant does not contain
1669  /// the alternative, this function returns null. In the case where the
1670  /// alternative is of type `void`, this function does nothing.
1671  ///
1672  /// ## Example
1673  /// ```cpp
1674  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1675  ///
1676  /// assert(*v.get_if<1>() == 42);
1677  ///
1678  /// *v.get_if<1>() = 24;
1679  ///
1680  /// assert(*v.get_if<1>() == 24);
1681  ///
1682  /// assert(v.get_if<0>() == nullptr);
1683  /// ```
1684  ///
1685  /// @tparam I The index of the alternative to access.
1686  ///
1687  /// @return A pointer to the accessed alternative, if applicable, or null
1688  template <size_t I>
1689  [[nodiscard]] constexpr
1690 #ifndef DOXYGEN
1691  typename detail::traits<detail::select_t<I, T...>>::const_pointer
1692 #else
1694 #endif
1695  get_if() const noexcept {
1696  using ptr_t = typename detail::traits<detail::select_t<I, T...>>::const_pointer;
1697  if constexpr (!std::is_void_v<ptr_t>) {
1698  ptr_t ret;
1699  if (index() == I) {
1700  ret = &data_().template get<I>();
1701  } else {
1702  ret = nullptr;
1703  }
1704  return ret;
1705  } else {
1706  return;
1707  }
1708  }
1709 
1710  /// @brief Gets an alternative pointer by type if the @ref variant holds it
1711  ///
1712  /// @details
1713  /// This functions tries to access an alternative by type. If the @ref
1714  /// variant contains the alternative, this function returns a pointer to
1715  /// the alternative, if applicable. If the @ref variant does not contain
1716  /// the alternative, this function returns null. In the case where the
1717  /// alternative is of type `void`, this function does nothing.
1718  ///
1719  /// This function only participates in overload resolution if the type is
1720  /// unique across all alternative types of the @ref variant. That is,
1721  /// `variant<A, B, A>` cannot use this function to access an alternative
1722  /// of type `A`, but it can use this fucntion to access an alternative of
1723  /// type `B`.
1724  ///
1725  /// ## Example
1726  /// ```cpp
1727  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1728  ///
1729  /// assert(*v.get_if<int>() == 42);
1730  ///
1731  /// *v.get_if<int>() = 24;
1732  ///
1733  /// assert(*v.get_if<int>() == 24);
1734  ///
1735  /// assert(v.get_if<bool>() == nullptr);
1736  /// ```
1737  ///
1738  /// @tparam I The index of the alternative to access.
1739  ///
1740  /// @return A pointer to the accessed alternative, if applicable, or null
1741  template <typename U>
1742 #ifndef DOXYGEN
1743  requires detail::is_unique_v<U, T...>
1744 #endif
1745  [[nodiscard]] constexpr
1746 #ifndef DOXYGEN
1747  typename detail::traits<U>::pointer
1748 #else
1749  POINTER
1750 #endif
1751  get_if() noexcept {
1752  return get_if<detail::index_of_v<U, T...>>();
1753  }
1754 
1755  /// @brief Gets an alternative pointer by type if the @ref variant holds it
1756  ///
1757  /// @details
1758  /// This functions tries to access an alternative by type. If the @ref
1759  /// variant contains the alternative, this function returns a pointer to
1760  /// the alternative, if applicable. If the @ref variant does not contain
1761  /// the alternative, this function returns null. In the case where the
1762  /// alternative is of type `void`, this function does nothing.
1763  ///
1764  /// This function only participates in overload resolution if the type is
1765  /// unique across all alternative types of the @ref variant. That is,
1766  /// `variant<A, B, A>` cannot use this function to access an alternative
1767  /// of type `A`, but it can use this fucntion to access an alternative of
1768  /// type `B`.
1769  ///
1770  /// ## Example
1771  /// ```cpp
1772  /// variant<bool, int, void> v{std::in_place_index<1>, 42};
1773  ///
1774  /// assert(*v.get_if<int>() == 42);
1775  ///
1776  /// *v.get_if<int>() = 24;
1777  ///
1778  /// assert(*v.get_if<int>() == 24);
1779  ///
1780  /// assert(v.get_if<bool>() == nullptr);
1781  /// ```
1782  ///
1783  /// @tparam I The index of the alternative to access.
1784  ///
1785  /// @return A pointer to the accessed alternative, if applicable, or null
1786  template <typename U>
1787 #ifndef DOXYGEN
1788  requires detail::is_unique_v<U, T...>
1789 #endif
1790  [[nodiscard]] constexpr
1791 #ifndef DOXYGEN
1792  typename detail::traits<U>::const_pointer
1793 #else
1795 #endif
1796  get_if() const noexcept {
1797  return get_if<detail::index_of_v<U, T...>>();
1798  }
1799 
1800  /// @brief Checks if a @ref variant contains a particular alternative.
1801  ///
1802  /// @details
1803  /// Given a type parameter, this function checks if the @ref variant currently
1804  /// holds an alternative that has the exact same type.
1805  ///
1806  /// ## Example
1807  /// ```cpp
1808  /// variant<int, bool, int> v1{std::in_place_index<0>, 42};
1809  ///
1810  /// assert(v1.holds_alternative<int>());
1811  ///
1812  /// variant<int, bool, int> v2{std::in_place_index<2>, 42};
1813  ///
1814  /// assert(v2.holds_alternative<int>());
1815  /// ```
1816  ///
1817  /// @return `true` if the @ref variant holds an alternative of the given type.
1818  template <typename U>
1819  [[nodiscard]] constexpr bool holds_alternative() const noexcept {
1820  if constexpr (detail::is_unique_v<U, T...>) {
1821  return index() == detail::index_of_v<U, T...>;
1822  } else {
1823  return holds_alt_impl<0, U>();
1824  }
1825  }
1826 
1827  /// @brief Calls a visitor callable with the contained alternative
1828  ///
1829  /// @details
1830  /// This function calls the visitor as `std::invoke(visitor, alternative)`
1831  /// and returns the result of that call, if any. As such, `visitor` *must*
1832  /// be able to accecpt any alternative type as an argument. In the case of
1833  /// an alternative of type `void`, the visitor must be callable as
1834  /// `std::invoke(visitor, void_v)`.
1835  ///
1836  /// Note that the @ref overload function can be helpful for defining a
1837  /// visitor inline.
1838  ///
1839  /// Also note that this function is implemented as a compile-time-defined
1840  /// jump table (array of function pointers). In performance critical
1841  /// applications, be wary of any assumptions about how well or poorly your
1842  /// compiler will optimize a call to this function.
1843  ///
1844  /// ## Example
1845  /// ```cpp
1846  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
1847  ///
1848  /// v1.visit(overload(
1849  /// [](bool bool_value) { assert(false); },
1850  /// [](int int_value) { assert(int_value == 42); },
1851  /// [](void_t void_value) { assert(false); }
1852  /// ));
1853  /// ```
1854  ///
1855  /// @param visitor The callable object that will be passed an alternative.
1856  /// @return The return value of the visitor, if any.
1857  template <typename V>
1858  constexpr
1859 #ifndef DOXYGEN
1860  detail::invoke_result_t<
1861  V&&,
1862  typename detail::traits<detail::select_t<0, T...>>::reference>
1863 #else
1864  DEDUCED
1865 #endif
1866  visit(V&& visitor) & {
1867  return detail::visit_impl<V, variant&, T...>(std::forward<V>(visitor), *this);
1868  }
1869 
1870  /// @brief Calls a visitor callable with the contained alternative
1871  ///
1872  /// @details
1873  /// This function calls the visitor as `std::invoke(visitor, alternative)`
1874  /// and returns the result of that call, if any. As such, `visitor` *must*
1875  /// be able to accecpt any alternative type as an argument. In the case of
1876  /// an alternative of type `void`, the visitor must be callable as
1877  /// `std::invoke(visitor, void_v)`.
1878  ///
1879  /// Note that the @ref overload function can be helpful for defining a
1880  /// visitor inline.
1881  ///
1882  /// Also note that this function is implemented as a compile-time-defined
1883  /// jump table (array of function pointers). In performance critical
1884  /// applications, be wary of any assumptions about how well or poorly your
1885  /// compiler will optimize a call to this function.
1886  ///
1887  /// ## Example
1888  /// ```cpp
1889  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
1890  ///
1891  /// v1.visit(overload(
1892  /// [](bool bool_value) { assert(false); },
1893  /// [](int int_value) { assert(int_value == 42); },
1894  /// [](void_t void_value) { assert(false); }
1895  /// ));
1896  /// ```
1897  ///
1898  /// @param visitor The callable object that will be passed an alternative.
1899  /// @return The return value of the visitor, if any.
1900  template <typename V>
1901  constexpr
1902 #ifndef DOXYGEN
1903  detail::invoke_result_t<
1904  V&&,
1905  typename detail::traits<detail::select_t<0, T...>>::const_reference>
1906 #else
1907  DEDUCED
1908 #endif
1909  visit(V&& visitor) const& {
1910  return detail::visit_impl<V, const variant&, T...>(std::forward<V>(visitor), *this);
1911  }
1912 
1913  /// @brief Calls a visitor callable with the contained alternative
1914  ///
1915  /// @details
1916  /// This function calls the visitor as `std::invoke(visitor, alternative)`
1917  /// and returns the result of that call, if any. As such, `visitor` *must*
1918  /// be able to accecpt any alternative type as an argument. In the case of
1919  /// an alternative of type `void`, the visitor must be callable as
1920  /// `std::invoke(visitor, void_v)`.
1921  ///
1922  /// Note that the @ref overload function can be helpful for defining a
1923  /// visitor inline.
1924  ///
1925  /// Also note that this function is implemented as a compile-time-defined
1926  /// jump table (array of function pointers). In performance critical
1927  /// applications, be wary of any assumptions about how well or poorly your
1928  /// compiler will optimize a call to this function.
1929  ///
1930  /// ## Example
1931  /// ```cpp
1932  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
1933  ///
1934  /// v1.visit(overload(
1935  /// [](bool bool_value) { assert(false); },
1936  /// [](int int_value) { assert(int_value == 42); },
1937  /// [](void_t void_value) { assert(false); }
1938  /// ));
1939  /// ```
1940  ///
1941  /// @param visitor The callable object that will be passed an alternative.
1942  /// @return The return value of the visitor, if any.
1943  template <typename V>
1944  constexpr
1945 #ifndef DOXYGEN
1946  detail::invoke_result_t<
1947  V&&,
1948  typename detail::traits<detail::select_t<0, T...>>::rvalue_reference>
1949 #else
1950  DEDUCED
1951 #endif
1952  visit(V&& visitor) && {
1953  return detail::visit_impl<V, variant&&, T...>(std::forward<V>(visitor),
1954  std::move(*this));
1955  }
1956 
1957  /// @brief Calls a visitor callable with the contained alternative
1958  ///
1959  /// @details
1960  /// This function calls the visitor as `std::invoke(visitor, alternative)`
1961  /// and returns the result of that call, if any. As such, `visitor` *must*
1962  /// be able to accecpt any alternative type as an argument. In the case of
1963  /// an alternative of type `void`, the visitor must be callable as
1964  /// `std::invoke(visitor, void_v)`.
1965  ///
1966  /// Note that the @ref overload function can be helpful for defining a
1967  /// visitor inline.
1968  ///
1969  /// Also note that this function is implemented as a compile-time-defined
1970  /// jump table (array of function pointers). In performance critical
1971  /// applications, be wary of any assumptions about how well or poorly your
1972  /// compiler will optimize a call to this function.
1973  ///
1974  /// ## Example
1975  /// ```cpp
1976  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
1977  ///
1978  /// v1.visit(overload(
1979  /// [](bool bool_value) { assert(false); },
1980  /// [](int int_value) { assert(int_value == 42); },
1981  /// [](void_t void_value) { assert(false); }
1982  /// ));
1983  /// ```
1984  ///
1985  /// @param visitor The callable object that will be passed an alternative.
1986  /// @return The return value of the visitor, if any.
1987  template <typename V>
1988  constexpr
1989 #ifndef DOXYGEN
1990  detail::invoke_result_t<
1991  V&&,
1992  typename detail::traits<detail::select_t<0, T...>>::const_rvalue_reference>
1993 #else
1994  DEDUCED
1995 #endif
1996  visit(V&& visitor) const&& {
1997  return detail::visit_impl<V, const variant&&, T...>(std::forward<V>(visitor),
1998  std::move(*this));
1999  }
2000 
2001  /// @brief Calls a visitor callable with the contained alternative and metadata
2002  ///
2003  /// @details
2004  /// This function calls the visitor as `std::invoke(visitor, alternative, info)`,
2005  /// and returns the result of that call, if any. As such, `visitor` *must* be
2006  /// able to accept any alternative type as an argument. In the case of an
2007  /// alternative of type `void`, the visitor must be callable as
2008  /// `std::invoke(visitor, void_v, info)`.
2009  ///
2010  /// The `info` argument passed to the visitor, which differentiates this
2011  /// function from `.visit(...)`, communicates `constexpr` information about
2012  /// the alternative being visited. The type of the `info` object is not
2013  /// meant to be named, but it has the API shown below. Note that `info` is
2014  /// always an empty type.
2015  ///
2016  /// ```
2017  /// struct alternative_info {
2018  /// // index of the alternative in the source variant
2019  /// static inline constexpr size_t index = ...;
2020  ///
2021  /// // type of the alternative as declared in the source variant
2022  /// using type = ...;
2023  /// };
2024  /// ```
2025  ///
2026  /// Note that the @ref overload function can be helpful for defining a
2027  /// visitor inline.
2028  ///
2029  /// Also note that this function is implemented as a compile-time-defined
2030  /// jump table (array of function pointers). In performance critical
2031  /// applications, be wary of any assumptions about how well or poorly your
2032  /// compiler will optimize a call to this function.
2033  ///
2034  /// ## Example
2035  /// ```
2036  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
2037  ///
2038  /// v1.visit_informed([](auto value, auto info) {
2039  /// if constexpr (info.index == 0) {
2040  /// assert(false);
2041  /// } else if constexpr (info.index == 1) {
2042  /// assert(value == 42);
2043  /// } else if constexpr (info.index == 2) {
2044  /// assert(false);
2045  /// }
2046  /// });
2047  /// ```
2048  ///
2049  /// @param visitor The callable object that will be passed an alternative.
2050  /// @return The return value of the visitor, if any.
2051  template <typename V>
2052  constexpr
2053 #ifndef DOXYGEN
2054  detail::invoke_result_t<
2055  V&&,
2056  typename detail::traits<detail::select_t<0, T...>>::reference,
2057  detail::alternative_info<0, variant>>
2058 #else
2059  DEDUCED
2060 #endif
2061  visit_informed(V&& visitor) & {
2062  return detail::visit_informed_impl<V, variant&, T...>(std::forward<V>(visitor),
2063  *this);
2064  }
2065 
2066  /// @brief Calls a visitor callable with the contained alternative and metadata
2067  ///
2068  /// @details
2069  /// This function calls the visitor as `std::invoke(visitor, alternative, info)`,
2070  /// and returns the result of that call, if any. As such, `visitor` *must* be
2071  /// able to accept any alternative type as an argument. In the case of an
2072  /// alternative of type `void`, the visitor must be callable as
2073  /// `std::invoke(visitor, void_v, info)`.
2074  ///
2075  /// The `info` argument passed to the visitor, which differentiates this
2076  /// function from `.visit(...)`, communicates `constexpr` information about
2077  /// the alternative being visited. The type of the `info` object is not
2078  /// meant to be named, but it has the API shown below. Note that `info` is
2079  /// always an empty type.
2080  ///
2081  /// ```
2082  /// struct alternative_info {
2083  /// // index of the alternative in the source variant
2084  /// static inline constexpr size_t index = ...;
2085  ///
2086  /// // type of the alternative as declared in the source variant
2087  /// using type = ...;
2088  /// };
2089  /// ```
2090  ///
2091  /// Note that the @ref overload function can be helpful for defining a
2092  /// visitor inline.
2093  ///
2094  /// Also note that this function is implemented as a compile-time-defined
2095  /// jump table (array of function pointers). In performance critical
2096  /// applications, be wary of any assumptions about how well or poorly your
2097  /// compiler will optimize a call to this function.
2098  ///
2099  /// ## Example
2100  /// ```
2101  /// const variant<bool, int, void> v1{std::in_place_index<1>, 42};
2102  ///
2103  /// v1.visit_informed([](auto value, auto info) {
2104  /// if constexpr (info.index == 0) {
2105  /// assert(false);
2106  /// } else if constexpr (info.index == 1) {
2107  /// assert(value == 42);
2108  /// } else if constexpr (info.index == 2) {
2109  /// assert(false);
2110  /// }
2111  /// });
2112  /// ```
2113  ///
2114  /// @param visitor The callable object that will be passed an alternative.
2115  /// @return The return value of the visitor, if any.
2116  template <typename V>
2117  constexpr
2118 #ifndef DOXYGEN
2119  detail::invoke_result_t<
2120  V&&,
2121  typename detail::traits<detail::select_t<0, T...>>::const_reference,
2122  detail::alternative_info<0, variant>>
2123 #else
2124  DEDUCED
2125 #endif
2126  visit_informed(V&& visitor) const& {
2127  return detail::visit_informed_impl<V, const variant&, T...>(
2128  std::forward<V>(visitor), *this);
2129  }
2130 
2131  /// @brief Calls a visitor callable with the contained alternative and metadata
2132  ///
2133  /// @details
2134  /// This function calls the visitor as `std::invoke(visitor, alternative, info)`,
2135  /// and returns the result of that call, if any. As such, `visitor` *must* be
2136  /// able to accept any alternative type as an argument. In the case of an
2137  /// alternative of type `void`, the visitor must be callable as
2138  /// `std::invoke(visitor, void_v, info)`.
2139  ///
2140  /// The `info` argument passed to the visitor, which differentiates this
2141  /// function from `.visit(...)`, communicates `constexpr` information about
2142  /// the alternative being visited. The type of the `info` object is not
2143  /// meant to be named, but it has the API shown below. Note that `info` is
2144  /// always an empty type.
2145  ///
2146  /// ```
2147  /// struct alternative_info {
2148  /// // index of the alternative in the source variant
2149  /// static inline constexpr size_t index = ...;
2150  ///
2151  /// // type of the alternative as declared in the source variant
2152  /// using type = ...;
2153  /// };
2154  /// ```
2155  ///
2156  /// Note that the @ref overload function can be helpful for defining a
2157  /// visitor inline.
2158  ///
2159  /// Also note that this function is implemented as a compile-time-defined
2160  /// jump table (array of function pointers). In performance critical
2161  /// applications, be wary of any assumptions about how well or poorly your
2162  /// compiler will optimize a call to this function.
2163  ///
2164  /// ## Example
2165  /// ```
2166  /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
2167  ///
2168  /// std::move(v1).visit_informed([](auto value, auto info) {
2169  /// if constexpr (info.index == 0) {
2170  /// assert(false);
2171  /// } else if constexpr (info.index == 1) {
2172  /// assert(value == 42);
2173  /// } else if constexpr (info.index == 2) {
2174  /// assert(false);
2175  /// }
2176  /// });
2177  /// ```
2178  ///
2179  /// @param visitor The callable object that will be passed an alternative.
2180  /// @return The return value of the visitor, if any.
2181  template <typename V>
2182  constexpr
2183 #ifndef DOXYGEN
2184  detail::invoke_result_t<
2185  V&&,
2186  typename detail::traits<detail::select_t<0, T...>>::rvalue_reference,
2187  detail::alternative_info<0, variant>>
2188 #else
2189  DEDUCED
2190 #endif
2191  visit_informed(V&& visitor) && {
2192  return detail::visit_informed_impl<V, variant&&, T...>(std::forward<V>(visitor),
2193  std::move(*this));
2194  }
2195 
2196  /// @brief Calls a visitor callable with the contained alternative and metadata
2197  ///
2198  /// @details
2199  /// This function calls the visitor as `std::invoke(visitor, alternative, info)`,
2200  /// and returns the result of that call, if any. As such, `visitor` *must* be
2201  /// able to accept any alternative type as an argument. In the case of an
2202  /// alternative of type `void`, the visitor must be callable as
2203  /// `std::invoke(visitor, void_v, info)`.
2204  ///
2205  /// The `info` argument passed to the visitor, which differentiates this
2206  /// function from `.visit(...)`, communicates `constexpr` information about
2207  /// the alternative being visited. The type of the `info` object is not
2208  /// meant to be named, but it has the API shown below. Note that `info` is
2209  /// always an empty type.
2210  ///
2211  /// ```
2212  /// struct alternative_info {
2213  /// // index of the alternative in the source variant
2214  /// static inline constexpr size_t index = ...;
2215  ///
2216  /// // type of the alternative as declared in the source variant
2217  /// using type = ...;
2218  /// };
2219  /// ```
2220  ///
2221  /// Note that the @ref overload function can be helpful for defining a
2222  /// visitor inline.
2223  ///
2224  /// Also note that this function is implemented as a compile-time-defined
2225  /// jump table (array of function pointers). In performance critical
2226  /// applications, be wary of any assumptions about how well or poorly your
2227  /// compiler will optimize a call to this function.
2228  ///
2229  /// ## Example
2230  /// ```
2231  /// const variant<bool, int, void> v1{std::in_place_index<1>, 42};
2232  ///
2233  /// std::move(v1).visit_informed([](auto value, auto info) {
2234  /// if constexpr (info.index == 0) {
2235  /// assert(false);
2236  /// } else if constexpr (info.index == 1) {
2237  /// assert(value == 42);
2238  /// } else if constexpr (info.index == 2) {
2239  /// assert(false);
2240  /// }
2241  /// });
2242  /// ```
2243  ///
2244  /// @param visitor The callable object that will be passed an alternative.
2245  /// @return The return value of the visitor, if any.
2246  template <typename V>
2247  constexpr
2248 #ifndef DOXYGEN
2249  detail::invoke_result_t<
2250  V&&,
2251  typename detail::traits<detail::select_t<0, T...>>::const_rvalue_reference,
2252  detail::alternative_info<0, variant>>
2253 #else
2254  DEDUCED
2255 #endif
2256  visit_informed(V&& visitor) const&& {
2257  return detail::visit_informed_impl<V, const variant&&, T...>(
2258  std::forward<V>(visitor), std::move(*this));
2259  }
2260 
2261  /// @brief Swaps two @ref variant instances
2262  ///
2263  /// @details
2264  /// If the two @ref variant instances contain the same alternative, the
2265  /// alternative values are swapped directly. Otherwise, the alternatives
2266  /// are swapped by moving out of the variants, destroying the old
2267  /// alternatives, and move constructed into the new alternatives.
2268  ///
2269  /// ## Example
2270  /// ```cpp
2271  /// variant<bool, int, void> v1{std::in_place_index<0>, true};
2272  ///
2273  /// variant<bool, int, void> v2{std::in_place_index<1>, 42};
2274  ///
2275  /// v1.swap(v2);
2276  ///
2277  /// assert(v1.index() == 1);
2278  ///
2279  /// assert(get<1>(v1) == 42);
2280  ///
2281  /// assert(v2.index() == 0);
2282  ///
2283  /// assert(get<2>(v2) == true);
2284  /// ```
2285  ///
2286  /// @param other The "other" @ref variant to swap with this @ref variant
2287  constexpr void swap(variant& other)
2288 #ifndef DOXYGEN
2289  noexcept(noexcept(data_().swap(other.data_())))
2290 #else
2292 #endif
2293  {
2294  data_().swap(other.data_());
2295  }
2296 };
2297 
2298 /// @relates variant
2299 /// @brief Checks if a @ref variant contains a particular alternative.
2300 ///
2301 /// @details
2302 /// Given a type parameter, this function checks if the @ref variant currently
2303 /// holds an alternative that has the exact same type.
2304 ///
2305 /// ## Example
2306 /// ```cpp
2307 /// variant<int, bool, int> v1{std::in_place_index<0>, 42};
2308 ///
2309 /// assert(holds_alternative<int>(v1));
2310 ///
2311 /// variant<int, bool, int> v2{std::in_place_index<2>, 42};
2312 ///
2313 /// assert(holds_alternative<int>(v2));
2314 /// ```
2315 ///
2316 /// @param v The @ref variant to check.
2317 /// @return `true` if the @ref variant holds an alternative of the given type.
2318 template <typename T, typename... U>
2319 constexpr bool holds_alternative(const variant<U...>& v) noexcept {
2320  return v.template holds_alternative<T>();
2321 }
2322 
2323 /// @relates variant
2324 /// @brief Gets a @ref variant alternative by index
2325 ///
2326 /// @details
2327 /// This function allows accessing @ref variant alternatives by index, which is
2328 /// provided as a template argument.
2329 ///
2330 /// ## Example
2331 /// ```cpp
2332 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2333 ///
2334 /// assert(get<1>(v) == 42);
2335 ///
2336 /// get<1>(v) = 24;
2337 ///
2338 /// assert(get<1>(v) == 24);
2339 /// ```
2340 ///
2341 /// @tparam I The index of the alternative to access.
2342 ///
2343 /// @param v The @ref variant to access
2344 ///
2345 /// @return A reference to the accessed alternative, if applicable.
2346 ///
2347 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2348 /// the alternative with the corresponding index.
2349 template <size_t I, typename... T>
2350 constexpr
2351 #ifndef DOXYGEN
2352  typename detail::traits<detail::select_t<I, T...>>::reference
2353 #else
2354  REFERENCE
2355 #endif
2356  get(variant<T...>& v) {
2357  return v.template get<I>();
2358 }
2359 
2360 /// @relates variant
2361 /// @brief Gets a @ref variant alternative by index
2362 ///
2363 /// @details
2364 /// This function allows accessing @ref variant alternatives by index, which is
2365 /// provided as a template argument.
2366 ///
2367 /// ## Example
2368 /// ```cpp
2369 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2370 ///
2371 /// assert(get<1>(v) == 42);
2372 ///
2373 /// get<1>(v) = 24;
2374 ///
2375 /// assert(get<1>(v) == 24);
2376 /// ```
2377 ///
2378 /// @tparam I The index of the alternative to access.
2379 ///
2380 /// @param v The @ref variant to access
2381 ///
2382 /// @return A reference to the accessed alternative, if applicable.
2383 ///
2384 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2385 /// the alternative with the corresponding index.
2386 template <size_t I, typename... T>
2387 constexpr
2388 #ifndef DOXYGEN
2389  typename detail::traits<detail::select_t<I, T...>>::const_reference
2390 #else
2392 #endif
2393  get(const variant<T...>& v) {
2394  return v.template get<I>();
2395 }
2396 
2397 /// @relates variant
2398 /// @brief Gets a @ref variant alternative by index
2399 ///
2400 /// @details
2401 /// This function allows accessing @ref variant alternatives by index, which is
2402 /// provided as a template argument.
2403 ///
2404 /// ## Example
2405 /// ```cpp
2406 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2407 ///
2408 /// assert(get<1>(v) == 42);
2409 ///
2410 /// get<1>(v) = 24;
2411 ///
2412 /// assert(get<1>(v) == 24);
2413 /// ```
2414 ///
2415 /// @tparam I The index of the alternative to access.
2416 ///
2417 /// @param v The @ref variant to access
2418 ///
2419 /// @return The accessed alternative value, if applicable.
2420 ///
2421 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2422 /// the alternative with the corresponding index.
2423 template <size_t I, typename... T>
2424 constexpr
2425 #ifndef DOXYGEN
2426  typename detail::traits<detail::select_t<I, T...>>::rvalue_reference
2427 #else
2429 #endif
2430  get(variant<T...>&& v) {
2431  return std::move(v).template get<I>();
2432 }
2433 
2434 /// @relates variant
2435 /// @brief Gets a @ref variant alternative by index
2436 ///
2437 /// @details
2438 /// This function allows accessing @ref variant alternatives by index, which is
2439 /// provided as a template argument.
2440 ///
2441 /// ## Example
2442 /// ```cpp
2443 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2444 ///
2445 /// assert(get<1>(v) == 42);
2446 ///
2447 /// get<1>(v) = 24;
2448 ///
2449 /// assert(get<1>(v) == 24);
2450 /// ```
2451 ///
2452 /// @tparam I The index of the alternative to access.
2453 ///
2454 /// @param v The @ref variant to access
2455 ///
2456 /// @return The accessed alternative value, if applicable.
2457 ///
2458 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2459 /// the alternative with the corresponding index.
2460 template <size_t I, typename... T>
2461 constexpr
2462 #ifndef DOXYGEN
2463  typename detail::traits<detail::select_t<I, T...>>::const_rvalue_reference
2464 #else
2466 #endif
2467  get(const variant<T...>&& v) {
2468  return std::move(v).template get<I>();
2469 }
2470 
2471 /// @relates variant
2472 /// @brief Gets a @ref variant alternative by type
2473 ///
2474 /// @details
2475 /// This function allows accessing @ref variant alternatives by type, which is
2476 /// provided as a template argument.
2477 ///
2478 /// This function only participates in overload resolution if the type is
2479 /// unique across all alternative types of the @ref variant. That is,
2480 /// `variant<A, B, A>` cannot use this function to access an alternative
2481 /// of type `A`, but it can use this fucntion to access an alternative of
2482 /// type `B`.
2483 ///
2484 /// ## Example
2485 /// ```cpp
2486 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2487 ///
2488 /// assert(get<int>(v) == 42);
2489 ///
2490 /// get<int>(v) = 24;
2491 ///
2492 /// assert(get<int>(v) == 24);
2493 /// ```
2494 ///
2495 /// @tparam U The type of the alternative to access.
2496 ///
2497 /// @param v The @ref variant to access.
2498 ///
2499 /// @return A reference to the accessed alternative, if applicable.
2500 ///
2501 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2502 /// the alternative with the corresponding type.
2503 template <typename T, typename... U>
2504 #ifndef DOXYGEN
2505  requires detail::is_unique_v<T, U...>
2506 #endif
2507 constexpr
2508 #ifndef DOXYGEN
2509  typename detail::traits<T>::reference
2510 #else
2511  REFERENCE
2512 #endif
2513  get(variant<U...>& v) {
2514  return v.template get<T>();
2515 }
2516 
2517 /// @relates variant
2518 /// @brief Gets a @ref variant alternative by type
2519 ///
2520 /// @details
2521 /// This function allows accessing @ref variant alternatives by type, which is
2522 /// provided as a template argument.
2523 ///
2524 /// This function only participates in overload resolution if the type is
2525 /// unique across all alternative types of the @ref variant. That is,
2526 /// `variant<A, B, A>` cannot use this function to access an alternative
2527 /// of type `A`, but it can use this fucntion to access an alternative of
2528 /// type `B`.
2529 ///
2530 /// ## Example
2531 /// ```cpp
2532 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2533 ///
2534 /// assert(get<int>(v) == 42);
2535 ///
2536 /// get<int>(v) = 24;
2537 ///
2538 /// assert(get<int>(v) == 24);
2539 /// ```
2540 ///
2541 /// @tparam U The type of the alternative to access.
2542 ///
2543 /// @param v The @ref variant to access.
2544 ///
2545 /// @return A reference to the accessed alternative, if applicable.
2546 ///
2547 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2548 /// the alternative with the corresponding type.
2549 template <typename T, typename... U>
2550 #ifndef DOXYGEN
2551  requires detail::is_unique_v<T, U...>
2552 #endif
2553 constexpr
2554 #ifndef DOXYGEN
2555  typename detail::traits<T>::const_reference
2556 #else
2558 #endif
2559  get(const variant<U...>& v) {
2560  return v.template get<T>();
2561 }
2562 
2563 /// @relates variant
2564 /// @brief Gets a @ref variant alternative by type
2565 ///
2566 /// @details
2567 /// This function allows accessing @ref variant alternatives by type, which is
2568 /// provided as a template argument.
2569 ///
2570 /// This function only participates in overload resolution if the type is
2571 /// unique across all alternative types of the @ref variant. That is,
2572 /// `variant<A, B, A>` cannot use this function to access an alternative
2573 /// of type `A`, but it can use this fucntion to access an alternative of
2574 /// type `B`.
2575 ///
2576 /// ## Example
2577 /// ```cpp
2578 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2579 ///
2580 /// assert(get<int>(v) == 42);
2581 ///
2582 /// get<int>(v) = 24;
2583 ///
2584 /// assert(get<int>(v) == 24);
2585 /// ```
2586 ///
2587 /// @tparam U The type of the alternative to access.
2588 ///
2589 /// @param v The @ref variant to access.
2590 ///
2591 /// @return The accessed alternative value, if applicable.
2592 ///
2593 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2594 /// the alternative with the corresponding type.
2595 template <typename T, typename... U>
2596 #ifndef DOXYGEN
2597  requires detail::is_unique_v<T, U...>
2598 #endif
2599 constexpr
2600 #ifndef DOXYGEN
2601  typename detail::traits<T>::rvalue_reference
2602 #else
2604 #endif
2605  get(variant<U...>&& v) {
2606  return std::move(v).template get<T>();
2607 }
2608 
2609 /// @relates variant
2610 /// @brief Gets a @ref variant alternative by type
2611 ///
2612 /// @details
2613 /// This function allows accessing @ref variant alternatives by type, which is
2614 /// provided as a template argument.
2615 ///
2616 /// This function only participates in overload resolution if the type is
2617 /// unique across all alternative types of the @ref variant. That is,
2618 /// `variant<A, B, A>` cannot use this function to access an alternative
2619 /// of type `A`, but it can use this fucntion to access an alternative of
2620 /// type `B`.
2621 ///
2622 /// ## Example
2623 /// ```cpp
2624 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2625 ///
2626 /// assert(get<int>(v) == 42);
2627 ///
2628 /// get<int>(v) = 24;
2629 ///
2630 /// assert(get<int>(v) == 24);
2631 /// ```
2632 ///
2633 /// @tparam U The type of the alternative to access.
2634 ///
2635 /// @param v The @ref variant to access.
2636 ///
2637 /// @return The accessed alternative value, if applicable.
2638 ///
2639 /// @throws bad_variant_access Thrown if the @ref variant does not contain
2640 /// the alternative with the corresponding type.
2641 template <typename T, typename... U>
2642 #ifndef DOXYGEN
2643  requires detail::is_unique_v<T, U...>
2644 #endif
2645 constexpr
2646 #ifndef DOXYGEN
2647  typename detail::traits<T>::const_rvalue_reference
2648 #else
2650 #endif
2651  get(const variant<U...>&& v) {
2652  return std::move(v).template get<T>();
2653 }
2654 
2655 /// @relates variant
2656 /// @brief Gets a @ref variant alternative pointer by index if the @ref variant holds it
2657 ///
2658 /// @details
2659 /// This functions tries to access a @ref variant alternative by index. If the
2660 /// @ref variant contains the alternative, this function returns a pointer to
2661 /// the alternative, if applicable. If the @ref variant does not contain the
2662 /// alternative, this function returns null. In the case where the alternative
2663 /// is of type `void`, this function does nothing.
2664 ///
2665 /// ## Example
2666 /// ```cpp
2667 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2668 ///
2669 /// assert(*get_if<1>(v) == 42);
2670 ///
2671 /// *get_if<1>(v) = 24;
2672 ///
2673 /// assert(*get_if<1>(v) == 24);
2674 ///
2675 /// assert(get_if<0>(v) == nullptr);
2676 /// ```
2677 ///
2678 /// @tparam I The index of the alternative to access.
2679 ///
2680 /// @param v The @ref variant to access
2681 ///
2682 /// @return A pointer to the accessed alternative, if applicable, or null
2683 template <size_t I, typename... T>
2684 constexpr
2685 #ifndef DOXYGEN
2686  typename detail::traits<detail::select_t<I, T...>>::pointer
2687 #else
2688  POINTER
2689 #endif
2690  get_if(variant<T...>& v) noexcept {
2691  return v.template get_if<I>();
2692 }
2693 
2694 /// @relates variant
2695 /// @brief Gets a @ref variant alternative pointer by index if the @ref variant holds it
2696 ///
2697 /// @details
2698 /// This functions tries to access a @ref variant alternative by index. If the
2699 /// @ref variant contains the alternative, this function returns a pointer to
2700 /// the alternative, if applicable. If the @ref variant does not contain the
2701 /// alternative, this function returns null. In the case where the alternative
2702 /// is of type `void`, this function does nothing.
2703 ///
2704 /// ## Example
2705 /// ```cpp
2706 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2707 ///
2708 /// assert(*get_if<1>(v) == 42);
2709 ///
2710 /// *get_if<1>(v) = 24;
2711 ///
2712 /// assert(*get_if<1>(v) == 24);
2713 ///
2714 /// assert(get_if<0>(v) == nullptr);
2715 /// ```
2716 ///
2717 /// @tparam I The index of the alternative to access.
2718 ///
2719 /// @param v The @ref variant to access
2720 ///
2721 /// @return A pointer to the accessed alternative, if applicable, or null
2722 template <size_t I, typename... T>
2723 constexpr
2724 #ifndef DOXYGEN
2725  typename detail::traits<detail::select_t<I, T...>>::const_pointer
2726 #else
2728 #endif
2729  get_if(const variant<T...>& v) noexcept {
2730  return v.template get_if<I>();
2731 }
2732 
2733 /// @relates variant
2734 /// @brief Gets a @ref variant alternative pointer by type if the @ref variant holds it
2735 ///
2736 /// @details
2737 /// This functions tries to access an alternative by type. If the @ref variant
2738 /// contains the alternative, this function returns a pointer to the
2739 /// alternative, if applicable. If the @ref variant does not contain the
2740 /// alternative, this function returns null. In the case where the alternative
2741 /// is of type `void`, this function does nothing.
2742 ///
2743 /// This function only participates in overload resolution if the type is
2744 /// unique across all alternative types of the @ref variant. That is,
2745 /// `variant<A, B, A>` cannot use this function to access an alternative
2746 /// of type `A`, but it can use this fucntion to access an alternative of
2747 /// type `B`.
2748 ///
2749 /// ## Example
2750 /// ```cpp
2751 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2752 ///
2753 /// assert(*get_if<int>(v) == 42);
2754 ///
2755 /// *get_if<int>(v) = 24;
2756 ///
2757 /// assert(*get_if<int>(v) == 24);
2758 ///
2759 /// assert(get_if<bool>(v) == nullptr);
2760 /// ```
2761 ///
2762 /// @tparam I The index of the alternative to access.
2763 ///
2764 /// @param v The @ref variant to access.
2765 ///
2766 /// @return A pointer to the accessed alternative, if applicable, or null
2767 template <typename T, typename... U>
2768 #ifndef DOXYGEN
2769  requires detail::is_unique_v<T, U...>
2770 #endif
2771 constexpr
2772 #ifndef DOXYGEN
2773  typename detail::traits<T>::pointer
2774 #else
2775  POINTER
2776 #endif
2777  get_if(variant<U...>& v) noexcept {
2778  return v.template get_if<T>();
2779 }
2780 
2781 /// @relates variant
2782 /// @brief Gets a @ref variant alternative pointer by type if the @ref variant holds it
2783 ///
2784 /// @details
2785 /// This functions tries to access an alternative by type. If the @ref variant
2786 /// contains the alternative, this function returns a pointer to the
2787 /// alternative, if applicable. If the @ref variant does not contain the
2788 /// alternative, this function returns null. In the case where the alternative
2789 /// is of type `void`, this function does nothing.
2790 ///
2791 /// This function only participates in overload resolution if the type is
2792 /// unique across all alternative types of the @ref variant. That is,
2793 /// `variant<A, B, A>` cannot use this function to access an alternative
2794 /// of type `A`, but it can use this fucntion to access an alternative of
2795 /// type `B`.
2796 ///
2797 /// ## Example
2798 /// ```cpp
2799 /// variant<bool, int, void> v{std::in_place_index<1>, 42};
2800 ///
2801 /// assert(*get_if<int>(v) == 42);
2802 ///
2803 /// *get_if<int>(v) = 24;
2804 ///
2805 /// assert(*get_if<int>(v) == 24);
2806 ///
2807 /// assert(get_if<bool>(v) == nullptr);
2808 /// ```
2809 ///
2810 /// @tparam I The index of the alternative to access.
2811 ///
2812 /// @param v The @ref variant to access.
2813 ///
2814 /// @return A pointer to the accessed alternative, if applicable, or null
2815 template <typename T, typename... U>
2816 #ifndef DOXYGEN
2817  requires detail::is_unique_v<T, U...>
2818 #endif
2819 constexpr
2820 #ifndef DOXYGEN
2821  typename detail::traits<T>::const_pointer
2822 #else
2824 #endif
2825  get_if(const variant<U...>& v) noexcept {
2826  return v.template get_if<T>();
2827 }
2828 
2829 /// @relates variant
2830 /// @brief Calls a visitor callable with the contained @ref variant alternatives
2831 ///
2832 /// @details
2833 /// This function calls the visitor as `std::invoke(visitor, alternative...)`
2834 /// and returns the result of that call, if any. As such, `visitor` *must*
2835 /// be able to accecpt any combination of alternative types as arguments. In
2836 /// the case of an alternative type `void`, the visitor must accept nothing
2837 /// for that argument. That is, the alternative type combination
2838 /// `int, void, int`, would result in the visitor being called as
2839 /// `std::invoke(visitor, int_value, int_value)`, essentially skipping the
2840 /// `void` alternative.
2841 ///
2842 /// Note that the @ref overload function can be helpful for defining a
2843 /// visitor inline.
2844 ///
2845 /// Also note that this function is implemented as a compile-time-defined
2846 /// jump table (array of function pointers). In performance critical
2847 /// applications, be wary of any assumptions about how well or poorly your
2848 /// compiler will optimize a call to this function.
2849 ///
2850 /// ## Example
2851 /// ```cpp
2852 /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
2853 /// variant<float, int> v2{std::in_place_index<0>, 3.14};
2854 ///
2855 /// visit(overload(
2856 /// [](bool val1, float val2) { assert(false); },
2857 /// [](int val1, float val2) { assert(val1 == 42); },
2858 /// [](float val2) { assert(false); },
2859 /// [](bool val1, int val2) { assert(false); },
2860 /// [](int val1, float val2) { assert(false); },
2861 /// [](int val2) { assert(false); }
2862 /// ), v1, v2);
2863 /// ```
2864 ///
2865 /// @param visitor The callable object that will be passed an alternative.
2866 ///
2867 /// @return The return value of the visitor, if any.
2868 template <typename V>
2869 constexpr
2870 #ifndef DOXYGEN
2871  std::invoke_result_t<V&&>
2872 #else
2873  DEDUCED
2874 #endif
2875  visit(V&& visitor) {
2876  return std::invoke(std::forward<V>(visitor));
2877 }
2878 
2879 /// @relates variant
2880 /// @brief Calls a visitor callable with the contained @ref variant alternatives
2881 ///
2882 /// @details
2883 /// This function calls the visitor as `std::invoke(visitor, alternative...)`
2884 /// and returns the result of that call, if any. As such, `visitor` *must*
2885 /// be able to accecpt any combination of alternative types as arguments. In
2886 /// the case of an alternative type `void`, the visitor must accept nothing
2887 /// for that argument. That is, the alternative type combination
2888 /// `int, void, int`, would result in the visitor being called as
2889 /// `std::invoke(visitor, int_value, int_value)`, essentially skipping the
2890 /// `void` alternative.
2891 ///
2892 /// Note that the @ref overload function can be helpful for defining a
2893 /// visitor inline.
2894 ///
2895 /// Also note that this function is implemented as a compile-time-defined
2896 /// jump table (array of function pointers). In performance critical
2897 /// applications, be wary of any assumptions about how well or poorly your
2898 /// compiler will optimize a call to this function.
2899 ///
2900 /// ## Example
2901 /// ```cpp
2902 /// variant<bool, int, void> v1{std::in_place_index<1>, 42};
2903 /// variant<float, int> v2{std::in_place_index<0>, 3.14};
2904 ///
2905 /// visit(overload(
2906 /// [](bool val1, float val2) { assert(false); },
2907 /// [](int val1, float val2) { assert(val1 == 42); },
2908 /// [](float val2) { assert(false); },
2909 /// [](bool val1, int val2) { assert(false); },
2910 /// [](int val1, float val2) { assert(false); },
2911 /// [](int val2) { assert(false); }
2912 /// ), v1, v2);
2913 /// ```
2914 ///
2915 /// @param visitor The callable object that will be passed an alternative.
2916 ///
2917 /// @param var0 The first variant to visit
2918 ///
2919 /// @param varn The remaining variant to visit
2920 ///
2921 /// @return The return value of the visitor, if any.
2922 template <typename V, typename T0, typename... TN>
2923 constexpr
2924 #ifndef DOXYGEN
2925  detail::invoke_result_t<V&&,
2926  decltype(get<0>(std::declval<T0&&>())),
2927  decltype(get<0>(std::declval<TN&&>()))...>
2928 #else
2929  DEDUCED
2930 #endif
2931  // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
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));
2935  } else {
2936  return std::forward<T0>(var0).visit(
2937  [visitor = std::forward<V>(visitor),
2938  ... varn = std::forward<TN>(varn)](auto&&... value) mutable {
2939  return visit(
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)...);
2946  },
2947  std::forward<TN>(varn)...);
2948  });
2949  }
2950 }
2951 
2952 /// @relates variant
2953 /// @brief Swaps two @ref variant instances
2954 ///
2955 /// @details
2956 /// If the two @ref variant instances contain the same alternative, the
2957 /// alternative values are swapped directly. Otherwise, the alternatives
2958 /// are swapped by moving out of the variants, destroying the old
2959 /// alternatives, and move constructed into the new alternatives.
2960 ///
2961 /// ## Example
2962 /// ```cpp
2963 /// variant<bool, int, void> v1{std::in_place_index<0>, true};
2964 ///
2965 /// variant<bool, int, void> v2{std::in_place_index<1>, 42};
2966 ///
2967 /// swap(v1, v2);
2968 ///
2969 /// assert(v1.index() == 1);
2970 ///
2971 /// assert(get<1>(v1) == 42);
2972 ///
2973 /// assert(v2.index() == 0);
2974 ///
2975 /// assert(get<2>(v2) == true);
2976 /// ```
2977 ///
2978 /// @param a The first variant in the swap
2979 /// @param b The second variant in the swap
2980 template <typename... T>
2981 constexpr void swap(variant<T...>& a, variant<T...>& b)
2982 #ifndef DOXYGEN
2983  noexcept(noexcept(a.swap(b)))
2984 #else
2986 #endif
2987 {
2988  a.swap(b);
2989 }
2990 
2991 /// @relates variant
2992 /// @class variant_size variant.hpp <sumty/variant.hpp>
2993 /// @brief Utility to get the number of alternatives in a @ref variant
2994 ///
2995 /// @details
2996 /// @ref varaint_size provides the number alternatives in the @ref variant,
2997 /// `T`, in the static constexpr member `value`.
2998 ///
2999 /// ## Example
3000 /// ```cpp
3001 /// assert(variant_size<variant<bool, int, void>>::value == 3);
3002 /// ```
3003 ///
3004 /// @tparam T The @ref variant type to get the size of
3005 template <typename T>
3006 struct variant_size
3007 #ifndef DOXYGEN
3008  : detail::variant_size_helper<T> {
3009 };
3010 #else
3011  ;
3012 #endif
3013 
3014 /// @relates variant_size
3015 /// @brief Utility to get the number of alternatives in a @ref variant
3016 ///
3017 /// @details
3018 /// @ref varaint_size_v provides the number alternatives in the @ref variant,
3019 /// `T`.
3020 ///
3021 /// ## Example
3022 /// ```cpp
3023 /// assert(variant_size_v<variant<bool, int, void>> == 3);
3024 /// ```
3025 ///
3026 /// @tparam T The @ref variant type to get the size of
3027 template <typename T>
3028 static inline constexpr size_t variant_size_v = variant_size<T>::value;
3029 
3030 /// @relates variant
3031 /// @class variant_alternative variant.hpp <sumty/variant.hpp>
3032 /// @brief Utility to get the type of a @ref variant alternative with some index
3033 ///
3034 /// @details
3035 /// @ref variant_alternative provides the type of an alternative with the
3036 /// index `I` in the member type, `type`.
3037 ///
3038 /// ## Example
3039 /// ```cpp
3040 /// assert(std::is_same_v<
3041 /// typename variant_alternative<1, variant<bool, int, void>>::type,
3042 /// int
3043 /// >);
3044 /// ```
3045 ///
3046 /// @tparam I The index of the @ref variant alternative
3047 ///
3048 /// @tparam T The @ref variant type containing the alternative
3049 template <size_t I, typename T>
3050 struct variant_alternative
3051 #ifndef DOXYGEN
3052  : detail::variant_alternative_helper<I, T> {
3053 };
3054 #else
3055  ;
3056 #endif
3057 
3058 /// @relates variant_alternative
3059 /// @brief Utility to get the type of a @ref variant alternative with some index
3060 ///
3061 /// @details
3062 /// @ref variant_alternative_t is the type of an alternative with the index `I`.
3063 ///
3064 /// ## Example
3065 /// ```cpp
3066 /// assert(std::is_same_v<
3067 /// variant_alternative_t<1, variant<bool, int, void>>, int>);
3068 /// ```
3069 ///
3070 /// @tparam I The index of the @variant alternative
3071 ///
3072 /// @tparam T The @ref variant type containing the alternative
3073 template <size_t I, typename T>
3074 using variant_alternative_t = typename variant_alternative<I, T>::type;
3075 
3076 /// @private
3077 template <typename... T>
3078  requires((true && ... && std::is_base_of_v<never, std::remove_cvref_t<T>>))
3079 class variant<T...> : public never {};
3080 
3081 } // namespace sumty
3082 
3083 #endif