xref: /freebsd-12.1/contrib/libc++/include/variant (revision b5893f02)
1aed8d94eSDimitry Andric// -*- C++ -*-
2aed8d94eSDimitry Andric//===------------------------------ variant -------------------------------===//
3aed8d94eSDimitry Andric//
4aed8d94eSDimitry Andric//                     The LLVM Compiler Infrastructure
5aed8d94eSDimitry Andric//
6aed8d94eSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open
7aed8d94eSDimitry Andric// Source Licenses. See LICENSE.TXT for details.
8aed8d94eSDimitry Andric//
9aed8d94eSDimitry Andric//===----------------------------------------------------------------------===//
10aed8d94eSDimitry Andric
11aed8d94eSDimitry Andric#ifndef _LIBCPP_VARIANT
12aed8d94eSDimitry Andric#define _LIBCPP_VARIANT
13aed8d94eSDimitry Andric
14aed8d94eSDimitry Andric/*
15aed8d94eSDimitry Andric   variant synopsis
16aed8d94eSDimitry Andric
17aed8d94eSDimitry Andricnamespace std {
18aed8d94eSDimitry Andric
19aed8d94eSDimitry Andric  // 20.7.2, class template variant
20aed8d94eSDimitry Andric  template <class... Types>
21aed8d94eSDimitry Andric  class variant {
22aed8d94eSDimitry Andric  public:
23aed8d94eSDimitry Andric
24aed8d94eSDimitry Andric    // 20.7.2.1, constructors
25aed8d94eSDimitry Andric    constexpr variant() noexcept(see below);
26*b5893f02SDimitry Andric    variant(const variant&);                // constexpr in C++20
27*b5893f02SDimitry Andric    variant(variant&&) noexcept(see below); // constexpr in C++20
28aed8d94eSDimitry Andric
29aed8d94eSDimitry Andric    template <class T> constexpr variant(T&&) noexcept(see below);
30aed8d94eSDimitry Andric
31aed8d94eSDimitry Andric    template <class T, class... Args>
32aed8d94eSDimitry Andric    constexpr explicit variant(in_place_type_t<T>, Args&&...);
33aed8d94eSDimitry Andric
34aed8d94eSDimitry Andric    template <class T, class U, class... Args>
35aed8d94eSDimitry Andric    constexpr explicit variant(
36aed8d94eSDimitry Andric        in_place_type_t<T>, initializer_list<U>, Args&&...);
37aed8d94eSDimitry Andric
38aed8d94eSDimitry Andric    template <size_t I, class... Args>
39aed8d94eSDimitry Andric    constexpr explicit variant(in_place_index_t<I>, Args&&...);
40aed8d94eSDimitry Andric
41aed8d94eSDimitry Andric    template <size_t I, class U, class... Args>
42aed8d94eSDimitry Andric    constexpr explicit variant(
43aed8d94eSDimitry Andric        in_place_index_t<I>, initializer_list<U>, Args&&...);
44aed8d94eSDimitry Andric
45aed8d94eSDimitry Andric    // 20.7.2.2, destructor
46aed8d94eSDimitry Andric    ~variant();
47aed8d94eSDimitry Andric
48aed8d94eSDimitry Andric    // 20.7.2.3, assignment
49*b5893f02SDimitry Andric    variant& operator=(const variant&);                // constexpr in C++20
50*b5893f02SDimitry Andric    variant& operator=(variant&&) noexcept(see below); // constexpr in C++20
51aed8d94eSDimitry Andric
52aed8d94eSDimitry Andric    template <class T> variant& operator=(T&&) noexcept(see below);
53aed8d94eSDimitry Andric
54aed8d94eSDimitry Andric    // 20.7.2.4, modifiers
55aed8d94eSDimitry Andric    template <class T, class... Args>
56540d2a8bSDimitry Andric    T& emplace(Args&&...);
57aed8d94eSDimitry Andric
58aed8d94eSDimitry Andric    template <class T, class U, class... Args>
59540d2a8bSDimitry Andric    T& emplace(initializer_list<U>, Args&&...);
60aed8d94eSDimitry Andric
61aed8d94eSDimitry Andric    template <size_t I, class... Args>
62540d2a8bSDimitry Andric    variant_alternative_t<I, variant>& emplace(Args&&...);
63aed8d94eSDimitry Andric
64aed8d94eSDimitry Andric    template <size_t I, class U, class...  Args>
65540d2a8bSDimitry Andric    variant_alternative_t<I, variant>& emplace(initializer_list<U>, Args&&...);
66aed8d94eSDimitry Andric
67aed8d94eSDimitry Andric    // 20.7.2.5, value status
68aed8d94eSDimitry Andric    constexpr bool valueless_by_exception() const noexcept;
69aed8d94eSDimitry Andric    constexpr size_t index() const noexcept;
70aed8d94eSDimitry Andric
71aed8d94eSDimitry Andric    // 20.7.2.6, swap
72aed8d94eSDimitry Andric    void swap(variant&) noexcept(see below);
73aed8d94eSDimitry Andric  };
74aed8d94eSDimitry Andric
75aed8d94eSDimitry Andric  // 20.7.3, variant helper classes
76aed8d94eSDimitry Andric  template <class T> struct variant_size; // undefined
77aed8d94eSDimitry Andric
78aed8d94eSDimitry Andric  template <class T>
7930785c0eSDimitry Andric  inline constexpr size_t variant_size_v = variant_size<T>::value;
80aed8d94eSDimitry Andric
81aed8d94eSDimitry Andric  template <class T> struct variant_size<const T>;
82aed8d94eSDimitry Andric  template <class T> struct variant_size<volatile T>;
83aed8d94eSDimitry Andric  template <class T> struct variant_size<const volatile T>;
84aed8d94eSDimitry Andric
85aed8d94eSDimitry Andric  template <class... Types>
86aed8d94eSDimitry Andric  struct variant_size<variant<Types...>>;
87aed8d94eSDimitry Andric
88aed8d94eSDimitry Andric  template <size_t I, class T> struct variant_alternative; // undefined
89aed8d94eSDimitry Andric
90aed8d94eSDimitry Andric  template <size_t I, class T>
91aed8d94eSDimitry Andric  using variant_alternative_t = typename variant_alternative<I, T>::type;
92aed8d94eSDimitry Andric
93aed8d94eSDimitry Andric  template <size_t I, class T> struct variant_alternative<I, const T>;
94aed8d94eSDimitry Andric  template <size_t I, class T> struct variant_alternative<I, volatile T>;
95aed8d94eSDimitry Andric  template <size_t I, class T> struct variant_alternative<I, const volatile T>;
96aed8d94eSDimitry Andric
97aed8d94eSDimitry Andric  template <size_t I, class... Types>
98aed8d94eSDimitry Andric  struct variant_alternative<I, variant<Types...>>;
99aed8d94eSDimitry Andric
10030785c0eSDimitry Andric  inline constexpr size_t variant_npos = -1;
101aed8d94eSDimitry Andric
102aed8d94eSDimitry Andric  // 20.7.4, value access
103aed8d94eSDimitry Andric  template <class T, class... Types>
104aed8d94eSDimitry Andric  constexpr bool holds_alternative(const variant<Types...>&) noexcept;
105aed8d94eSDimitry Andric
106aed8d94eSDimitry Andric  template <size_t I, class... Types>
107aed8d94eSDimitry Andric  constexpr variant_alternative_t<I, variant<Types...>>&
108aed8d94eSDimitry Andric  get(variant<Types...>&);
109aed8d94eSDimitry Andric
110aed8d94eSDimitry Andric  template <size_t I, class... Types>
111aed8d94eSDimitry Andric  constexpr variant_alternative_t<I, variant<Types...>>&&
112aed8d94eSDimitry Andric  get(variant<Types...>&&);
113aed8d94eSDimitry Andric
114aed8d94eSDimitry Andric  template <size_t I, class... Types>
115aed8d94eSDimitry Andric  constexpr variant_alternative_t<I, variant<Types...>> const&
116aed8d94eSDimitry Andric  get(const variant<Types...>&);
117aed8d94eSDimitry Andric
118aed8d94eSDimitry Andric  template <size_t I, class... Types>
119aed8d94eSDimitry Andric  constexpr variant_alternative_t<I, variant<Types...>> const&&
120aed8d94eSDimitry Andric  get(const variant<Types...>&&);
121aed8d94eSDimitry Andric
122aed8d94eSDimitry Andric  template <class T, class...  Types>
123aed8d94eSDimitry Andric  constexpr T& get(variant<Types...>&);
124aed8d94eSDimitry Andric
125aed8d94eSDimitry Andric  template <class T, class... Types>
126aed8d94eSDimitry Andric  constexpr T&& get(variant<Types...>&&);
127aed8d94eSDimitry Andric
128aed8d94eSDimitry Andric  template <class T, class... Types>
129aed8d94eSDimitry Andric  constexpr const T& get(const variant<Types...>&);
130aed8d94eSDimitry Andric
131aed8d94eSDimitry Andric  template <class T, class... Types>
132aed8d94eSDimitry Andric  constexpr const T&& get(const variant<Types...>&&);
133aed8d94eSDimitry Andric
134aed8d94eSDimitry Andric  template <size_t I, class... Types>
135aed8d94eSDimitry Andric  constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
136aed8d94eSDimitry Andric  get_if(variant<Types...>*) noexcept;
137aed8d94eSDimitry Andric
138aed8d94eSDimitry Andric  template <size_t I, class... Types>
139aed8d94eSDimitry Andric  constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
140aed8d94eSDimitry Andric  get_if(const variant<Types...>*) noexcept;
141aed8d94eSDimitry Andric
142aed8d94eSDimitry Andric  template <class T, class... Types>
143aed8d94eSDimitry Andric  constexpr add_pointer_t<T>
144aed8d94eSDimitry Andric  get_if(variant<Types...>*) noexcept;
145aed8d94eSDimitry Andric
146aed8d94eSDimitry Andric  template <class T, class... Types>
147aed8d94eSDimitry Andric  constexpr add_pointer_t<const T>
148aed8d94eSDimitry Andric  get_if(const variant<Types...>*) noexcept;
149aed8d94eSDimitry Andric
150aed8d94eSDimitry Andric  // 20.7.5, relational operators
151aed8d94eSDimitry Andric  template <class... Types>
152aed8d94eSDimitry Andric  constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
153aed8d94eSDimitry Andric
154aed8d94eSDimitry Andric  template <class... Types>
155aed8d94eSDimitry Andric  constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
156aed8d94eSDimitry Andric
157aed8d94eSDimitry Andric  template <class... Types>
158aed8d94eSDimitry Andric  constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
159aed8d94eSDimitry Andric
160aed8d94eSDimitry Andric  template <class... Types>
161aed8d94eSDimitry Andric  constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
162aed8d94eSDimitry Andric
163aed8d94eSDimitry Andric  template <class... Types>
164aed8d94eSDimitry Andric  constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
165aed8d94eSDimitry Andric
166aed8d94eSDimitry Andric  template <class... Types>
167aed8d94eSDimitry Andric  constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
168aed8d94eSDimitry Andric
169aed8d94eSDimitry Andric  // 20.7.6, visitation
170aed8d94eSDimitry Andric  template <class Visitor, class... Variants>
171aed8d94eSDimitry Andric  constexpr see below visit(Visitor&&, Variants&&...);
172aed8d94eSDimitry Andric
173aed8d94eSDimitry Andric  // 20.7.7, class monostate
174aed8d94eSDimitry Andric  struct monostate;
175aed8d94eSDimitry Andric
176aed8d94eSDimitry Andric  // 20.7.8, monostate relational operators
177aed8d94eSDimitry Andric  constexpr bool operator<(monostate, monostate) noexcept;
178aed8d94eSDimitry Andric  constexpr bool operator>(monostate, monostate) noexcept;
179aed8d94eSDimitry Andric  constexpr bool operator<=(monostate, monostate) noexcept;
180aed8d94eSDimitry Andric  constexpr bool operator>=(monostate, monostate) noexcept;
181aed8d94eSDimitry Andric  constexpr bool operator==(monostate, monostate) noexcept;
182aed8d94eSDimitry Andric  constexpr bool operator!=(monostate, monostate) noexcept;
183aed8d94eSDimitry Andric
184aed8d94eSDimitry Andric  // 20.7.9, specialized algorithms
185aed8d94eSDimitry Andric  template <class... Types>
186aed8d94eSDimitry Andric  void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
187aed8d94eSDimitry Andric
188aed8d94eSDimitry Andric  // 20.7.10, class bad_variant_access
189aed8d94eSDimitry Andric  class bad_variant_access;
190aed8d94eSDimitry Andric
191aed8d94eSDimitry Andric  // 20.7.11, hash support
192aed8d94eSDimitry Andric  template <class T> struct hash;
193aed8d94eSDimitry Andric  template <class... Types> struct hash<variant<Types...>>;
194aed8d94eSDimitry Andric  template <> struct hash<monostate>;
195aed8d94eSDimitry Andric
196aed8d94eSDimitry Andric} // namespace std
197aed8d94eSDimitry Andric
198aed8d94eSDimitry Andric*/
199aed8d94eSDimitry Andric
200aed8d94eSDimitry Andric#include <__config>
201aed8d94eSDimitry Andric#include <__tuple>
202aed8d94eSDimitry Andric#include <array>
203aed8d94eSDimitry Andric#include <exception>
204aed8d94eSDimitry Andric#include <functional>
205aed8d94eSDimitry Andric#include <initializer_list>
206aed8d94eSDimitry Andric#include <new>
207aed8d94eSDimitry Andric#include <tuple>
208aed8d94eSDimitry Andric#include <type_traits>
209aed8d94eSDimitry Andric#include <utility>
210b2c7081bSDimitry Andric#include <limits>
211*b5893f02SDimitry Andric#include <version>
212aed8d94eSDimitry Andric
213aed8d94eSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
214aed8d94eSDimitry Andric#pragma GCC system_header
215aed8d94eSDimitry Andric#endif
216aed8d94eSDimitry Andric
217b2c7081bSDimitry Andric_LIBCPP_PUSH_MACROS
218b2c7081bSDimitry Andric#include <__undef_macros>
219b2c7081bSDimitry Andric
220aed8d94eSDimitry Andricnamespace std { // explicitly not using versioning namespace
221aed8d94eSDimitry Andric
222*b5893f02SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception {
223aed8d94eSDimitry Andricpublic:
224aed8d94eSDimitry Andric  virtual const char* what() const _NOEXCEPT;
225aed8d94eSDimitry Andric};
226aed8d94eSDimitry Andric
227aed8d94eSDimitry Andric} // namespace std
228aed8d94eSDimitry Andric
229aed8d94eSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
230aed8d94eSDimitry Andric
231aed8d94eSDimitry Andric#if _LIBCPP_STD_VER > 14
232aed8d94eSDimitry Andric
233aed8d94eSDimitry Andric_LIBCPP_NORETURN
234aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
235*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
236aed8d94eSDimitry Andricvoid __throw_bad_variant_access() {
237aed8d94eSDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS
238aed8d94eSDimitry Andric        throw bad_variant_access();
239aed8d94eSDimitry Andric#else
240aed8d94eSDimitry Andric        _VSTD::abort();
241aed8d94eSDimitry Andric#endif
242aed8d94eSDimitry Andric}
243aed8d94eSDimitry Andric
244aed8d94eSDimitry Andrictemplate <class... _Types>
245aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS variant;
246aed8d94eSDimitry Andric
247aed8d94eSDimitry Andrictemplate <class _Tp>
248aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size;
249aed8d94eSDimitry Andric
250aed8d94eSDimitry Andrictemplate <class _Tp>
25130785c0eSDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t variant_size_v = variant_size<_Tp>::value;
252aed8d94eSDimitry Andric
253aed8d94eSDimitry Andrictemplate <class _Tp>
254aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
255aed8d94eSDimitry Andric
256aed8d94eSDimitry Andrictemplate <class _Tp>
257aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {};
258aed8d94eSDimitry Andric
259aed8d94eSDimitry Andrictemplate <class _Tp>
260aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp>
261aed8d94eSDimitry Andric    : variant_size<_Tp> {};
262aed8d94eSDimitry Andric
263aed8d94eSDimitry Andrictemplate <class... _Types>
264aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>>
265aed8d94eSDimitry Andric    : integral_constant<size_t, sizeof...(_Types)> {};
266aed8d94eSDimitry Andric
267aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp>
268aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative;
269aed8d94eSDimitry Andric
270aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp>
271aed8d94eSDimitry Andricusing variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type;
272aed8d94eSDimitry Andric
273aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp>
274aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp>
275aed8d94eSDimitry Andric    : add_const<variant_alternative_t<_Ip, _Tp>> {};
276aed8d94eSDimitry Andric
277aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp>
278aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, volatile _Tp>
279aed8d94eSDimitry Andric    : add_volatile<variant_alternative_t<_Ip, _Tp>> {};
280aed8d94eSDimitry Andric
281aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp>
282aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp>
283aed8d94eSDimitry Andric    : add_cv<variant_alternative_t<_Ip, _Tp>> {};
284aed8d94eSDimitry Andric
285aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
286aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> {
28724d58133SDimitry Andric  static_assert(_Ip < sizeof...(_Types), "Index out of bounds in std::variant_alternative<>");
288aed8d94eSDimitry Andric  using type = __type_pack_element<_Ip, _Types...>;
289aed8d94eSDimitry Andric};
290aed8d94eSDimitry Andric
29130785c0eSDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t variant_npos = static_cast<size_t>(-1);
292b2c7081bSDimitry Andric
293b2c7081bSDimitry Andricconstexpr int __choose_index_type(unsigned int __num_elem) {
294b2c7081bSDimitry Andric  if (__num_elem < std::numeric_limits<unsigned char>::max())
295b2c7081bSDimitry Andric    return 0;
296b2c7081bSDimitry Andric  if (__num_elem < std::numeric_limits<unsigned short>::max())
297b2c7081bSDimitry Andric    return 1;
298b2c7081bSDimitry Andric  return 2;
299b2c7081bSDimitry Andric}
300b2c7081bSDimitry Andric
301b2c7081bSDimitry Andrictemplate <size_t _NumAlts>
302b2c7081bSDimitry Andricusing __variant_index_t =
303b2c7081bSDimitry Andric#ifndef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
304b2c7081bSDimitry Andric  unsigned int;
305b2c7081bSDimitry Andric#else
306b2c7081bSDimitry Andric  std::tuple_element_t<
307b2c7081bSDimitry Andric      __choose_index_type(_NumAlts),
308b2c7081bSDimitry Andric      std::tuple<unsigned char, unsigned short, unsigned int>
309b2c7081bSDimitry Andric  >;
310b2c7081bSDimitry Andric#endif
311b2c7081bSDimitry Andric
312b2c7081bSDimitry Andrictemplate <class _IndexType>
313b2c7081bSDimitry Andricconstexpr _IndexType __variant_npos = static_cast<_IndexType>(-1);
314aed8d94eSDimitry Andric
315aed8d94eSDimitry Andricnamespace __find_detail {
316aed8d94eSDimitry Andric
317aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
318aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
319aed8d94eSDimitry Andricconstexpr size_t __find_index() {
320aed8d94eSDimitry Andric  constexpr bool __matches[] = {is_same_v<_Tp, _Types>...};
321aed8d94eSDimitry Andric  size_t __result = __not_found;
322aed8d94eSDimitry Andric  for (size_t __i = 0; __i < sizeof...(_Types); ++__i) {
323aed8d94eSDimitry Andric    if (__matches[__i]) {
324aed8d94eSDimitry Andric      if (__result != __not_found) {
325aed8d94eSDimitry Andric        return __ambiguous;
326aed8d94eSDimitry Andric      }
327aed8d94eSDimitry Andric      __result = __i;
328aed8d94eSDimitry Andric    }
329aed8d94eSDimitry Andric  }
330aed8d94eSDimitry Andric  return __result;
331aed8d94eSDimitry Andric}
332aed8d94eSDimitry Andric
333aed8d94eSDimitry Andrictemplate <size_t _Index>
334aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl
335aed8d94eSDimitry Andric    : integral_constant<size_t, _Index> {};
336aed8d94eSDimitry Andric
337aed8d94eSDimitry Andrictemplate <>
338aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl<__not_found> {};
339aed8d94eSDimitry Andric
340aed8d94eSDimitry Andrictemplate <>
341aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl<__ambiguous> {};
342aed8d94eSDimitry Andric
343aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
344aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae
345aed8d94eSDimitry Andric    : __find_unambiguous_index_sfinae_impl<__find_index<_Tp, _Types...>()> {};
346aed8d94eSDimitry Andric
347aed8d94eSDimitry Andric} // namespace __find_detail
348aed8d94eSDimitry Andric
349aed8d94eSDimitry Andricnamespace __variant_detail {
350aed8d94eSDimitry Andric
351aed8d94eSDimitry Andricstruct __valueless_t {};
352aed8d94eSDimitry Andric
353aed8d94eSDimitry Andricenum class _Trait { _TriviallyAvailable, _Available, _Unavailable };
354aed8d94eSDimitry Andric
355aed8d94eSDimitry Andrictemplate <typename _Tp,
356aed8d94eSDimitry Andric          template <typename> class _IsTriviallyAvailable,
357aed8d94eSDimitry Andric          template <typename> class _IsAvailable>
358aed8d94eSDimitry Andricconstexpr _Trait __trait =
359aed8d94eSDimitry Andric    _IsTriviallyAvailable<_Tp>::value
360aed8d94eSDimitry Andric        ? _Trait::_TriviallyAvailable
361aed8d94eSDimitry Andric        : _IsAvailable<_Tp>::value ? _Trait::_Available : _Trait::_Unavailable;
362aed8d94eSDimitry Andric
363aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
364aed8d94eSDimitry Andricconstexpr _Trait __common_trait(initializer_list<_Trait> __traits) {
365aed8d94eSDimitry Andric  _Trait __result = _Trait::_TriviallyAvailable;
366aed8d94eSDimitry Andric  for (_Trait __t : __traits) {
367aed8d94eSDimitry Andric    if (static_cast<int>(__t) > static_cast<int>(__result)) {
368aed8d94eSDimitry Andric      __result = __t;
369aed8d94eSDimitry Andric    }
370aed8d94eSDimitry Andric  }
371aed8d94eSDimitry Andric  return __result;
372aed8d94eSDimitry Andric}
373aed8d94eSDimitry Andric
374aed8d94eSDimitry Andrictemplate <typename... _Types>
375aed8d94eSDimitry Andricstruct __traits {
376aed8d94eSDimitry Andric  static constexpr _Trait __copy_constructible_trait =
377aed8d94eSDimitry Andric      __common_trait({__trait<_Types,
378aed8d94eSDimitry Andric                              is_trivially_copy_constructible,
379aed8d94eSDimitry Andric                              is_copy_constructible>...});
380aed8d94eSDimitry Andric
381aed8d94eSDimitry Andric  static constexpr _Trait __move_constructible_trait =
382aed8d94eSDimitry Andric      __common_trait({__trait<_Types,
383aed8d94eSDimitry Andric                              is_trivially_move_constructible,
384aed8d94eSDimitry Andric                              is_move_constructible>...});
385aed8d94eSDimitry Andric
386aed8d94eSDimitry Andric  static constexpr _Trait __copy_assignable_trait = __common_trait(
387aed8d94eSDimitry Andric      {__copy_constructible_trait,
388aed8d94eSDimitry Andric       __trait<_Types, is_trivially_copy_assignable, is_copy_assignable>...});
389aed8d94eSDimitry Andric
390aed8d94eSDimitry Andric  static constexpr _Trait __move_assignable_trait = __common_trait(
391aed8d94eSDimitry Andric      {__move_constructible_trait,
392aed8d94eSDimitry Andric       __trait<_Types, is_trivially_move_assignable, is_move_assignable>...});
393aed8d94eSDimitry Andric
394aed8d94eSDimitry Andric  static constexpr _Trait __destructible_trait = __common_trait(
395aed8d94eSDimitry Andric      {__trait<_Types, is_trivially_destructible, is_destructible>...});
396aed8d94eSDimitry Andric};
397aed8d94eSDimitry Andric
398aed8d94eSDimitry Andricnamespace __access {
399aed8d94eSDimitry Andric
400aed8d94eSDimitry Andricstruct __union {
401aed8d94eSDimitry Andric  template <class _Vp>
402aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
403aed8d94eSDimitry Andric  static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<0>) {
404aed8d94eSDimitry Andric    return _VSTD::forward<_Vp>(__v).__head;
405aed8d94eSDimitry Andric  }
406aed8d94eSDimitry Andric
407aed8d94eSDimitry Andric  template <class _Vp, size_t _Ip>
408aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
409aed8d94eSDimitry Andric  static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<_Ip>) {
410aed8d94eSDimitry Andric    return __get_alt(_VSTD::forward<_Vp>(__v).__tail, in_place_index<_Ip - 1>);
411aed8d94eSDimitry Andric  }
412aed8d94eSDimitry Andric};
413aed8d94eSDimitry Andric
414aed8d94eSDimitry Andricstruct __base {
415aed8d94eSDimitry Andric  template <size_t _Ip, class _Vp>
416aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
417aed8d94eSDimitry Andric  static constexpr auto&& __get_alt(_Vp&& __v) {
418aed8d94eSDimitry Andric    return __union::__get_alt(_VSTD::forward<_Vp>(__v).__data,
419aed8d94eSDimitry Andric                              in_place_index<_Ip>);
420aed8d94eSDimitry Andric  }
421aed8d94eSDimitry Andric};
422aed8d94eSDimitry Andric
423aed8d94eSDimitry Andricstruct __variant {
424aed8d94eSDimitry Andric  template <size_t _Ip, class _Vp>
425aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
426aed8d94eSDimitry Andric  static constexpr auto&& __get_alt(_Vp&& __v) {
427aed8d94eSDimitry Andric    return __base::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v).__impl);
428aed8d94eSDimitry Andric  }
429aed8d94eSDimitry Andric};
430aed8d94eSDimitry Andric
431aed8d94eSDimitry Andric} // namespace __access
432aed8d94eSDimitry Andric
433aed8d94eSDimitry Andricnamespace __visitation {
434aed8d94eSDimitry Andric
435aed8d94eSDimitry Andricstruct __base {
436aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
437aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
438aed8d94eSDimitry Andric  static constexpr decltype(auto)
439aed8d94eSDimitry Andric  __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
440aed8d94eSDimitry Andric    constexpr auto __fdiagonal =
441aed8d94eSDimitry Andric        __make_fdiagonal<_Visitor&&,
442aed8d94eSDimitry Andric                         decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>();
443aed8d94eSDimitry Andric    return __fdiagonal[__index](_VSTD::forward<_Visitor>(__visitor),
444aed8d94eSDimitry Andric                                _VSTD::forward<_Vs>(__vs).__as_base()...);
445aed8d94eSDimitry Andric  }
446aed8d94eSDimitry Andric
447aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
448aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
449aed8d94eSDimitry Andric  static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor,
450aed8d94eSDimitry Andric                                              _Vs&&... __vs) {
451aed8d94eSDimitry Andric    constexpr auto __fmatrix =
452aed8d94eSDimitry Andric        __make_fmatrix<_Visitor&&,
453aed8d94eSDimitry Andric                       decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>();
4545517e702SDimitry Andric    return __at(__fmatrix, __vs.index()...)(
4555517e702SDimitry Andric        _VSTD::forward<_Visitor>(__visitor),
456aed8d94eSDimitry Andric        _VSTD::forward<_Vs>(__vs).__as_base()...);
457aed8d94eSDimitry Andric  }
458aed8d94eSDimitry Andric
459aed8d94eSDimitry Andricprivate:
460aed8d94eSDimitry Andric  template <class _Tp>
461aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
4625517e702SDimitry Andric  static constexpr const _Tp& __at(const _Tp& __elem) { return __elem; }
463aed8d94eSDimitry Andric
4645517e702SDimitry Andric  template <class _Tp, size_t _Np, typename... _Indices>
465aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
466aed8d94eSDimitry Andric  static constexpr auto&& __at(const array<_Tp, _Np>& __elems,
4675517e702SDimitry Andric                               size_t __index, _Indices... __indices) {
4685517e702SDimitry Andric    return __at(__elems[__index], __indices...);
469aed8d94eSDimitry Andric  }
470aed8d94eSDimitry Andric
471aed8d94eSDimitry Andric  template <class _Fp, class... _Fs>
472aed8d94eSDimitry Andric  static constexpr void __std_visit_visitor_return_type_check() {
473aed8d94eSDimitry Andric    static_assert(
474aed8d94eSDimitry Andric        __all<is_same_v<_Fp, _Fs>...>::value,
475aed8d94eSDimitry Andric        "`std::visit` requires the visitor to have a single return type.");
476aed8d94eSDimitry Andric  }
477aed8d94eSDimitry Andric
478aed8d94eSDimitry Andric  template <class... _Fs>
479aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
480aed8d94eSDimitry Andric  static constexpr auto __make_farray(_Fs&&... __fs) {
4814ba319b5SDimitry Andric    __std_visit_visitor_return_type_check<__uncvref_t<_Fs>...>();
4824ba319b5SDimitry Andric    using __result = array<common_type_t<__uncvref_t<_Fs>...>, sizeof...(_Fs)>;
483aed8d94eSDimitry Andric    return __result{{_VSTD::forward<_Fs>(__fs)...}};
484aed8d94eSDimitry Andric  }
485aed8d94eSDimitry Andric
486540d2a8bSDimitry Andric  template <std::size_t... _Is>
487aed8d94eSDimitry Andric  struct __dispatcher {
488540d2a8bSDimitry Andric    template <class _Fp, class... _Vs>
489540d2a8bSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY
490aed8d94eSDimitry Andric    static constexpr decltype(auto) __dispatch(_Fp __f, _Vs... __vs) {
491aed8d94eSDimitry Andric        return __invoke_constexpr(
492aed8d94eSDimitry Andric            static_cast<_Fp>(__f),
493aed8d94eSDimitry Andric            __access::__base::__get_alt<_Is>(static_cast<_Vs>(__vs))...);
494aed8d94eSDimitry Andric    }
495aed8d94eSDimitry Andric  };
496540d2a8bSDimitry Andric
497540d2a8bSDimitry Andric  template <class _Fp, class... _Vs, size_t... _Is>
498540d2a8bSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
499540d2a8bSDimitry Andric  static constexpr auto __make_dispatch(index_sequence<_Is...>) {
500540d2a8bSDimitry Andric    return __dispatcher<_Is...>::template __dispatch<_Fp, _Vs...>;
501aed8d94eSDimitry Andric  }
502aed8d94eSDimitry Andric
503aed8d94eSDimitry Andric  template <size_t _Ip, class _Fp, class... _Vs>
504aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
505aed8d94eSDimitry Andric  static constexpr auto __make_fdiagonal_impl() {
506aed8d94eSDimitry Andric    return __make_dispatch<_Fp, _Vs...>(
507aed8d94eSDimitry Andric        index_sequence<(__identity<_Vs>{}, _Ip)...>{});
508aed8d94eSDimitry Andric  }
509aed8d94eSDimitry Andric
510aed8d94eSDimitry Andric  template <class _Fp, class... _Vs, size_t... _Is>
511aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
512aed8d94eSDimitry Andric  static constexpr auto __make_fdiagonal_impl(index_sequence<_Is...>) {
513aed8d94eSDimitry Andric    return __base::__make_farray(__make_fdiagonal_impl<_Is, _Fp, _Vs...>()...);
514aed8d94eSDimitry Andric  }
515aed8d94eSDimitry Andric
516aed8d94eSDimitry Andric  template <class _Fp, class _Vp, class... _Vs>
517aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
518aed8d94eSDimitry Andric  static constexpr auto __make_fdiagonal() {
5194ba319b5SDimitry Andric    constexpr size_t _Np = __uncvref_t<_Vp>::__size();
5204ba319b5SDimitry Andric    static_assert(__all<(_Np == __uncvref_t<_Vs>::__size())...>::value);
521aed8d94eSDimitry Andric    return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<_Np>{});
522aed8d94eSDimitry Andric  }
523aed8d94eSDimitry Andric
524aed8d94eSDimitry Andric  template <class _Fp, class... _Vs, size_t... _Is>
525aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
526aed8d94eSDimitry Andric  static constexpr auto __make_fmatrix_impl(index_sequence<_Is...> __is) {
527aed8d94eSDimitry Andric    return __make_dispatch<_Fp, _Vs...>(__is);
528aed8d94eSDimitry Andric  }
529aed8d94eSDimitry Andric
530aed8d94eSDimitry Andric  template <class _Fp, class... _Vs, size_t... _Is, size_t... _Js, class... _Ls>
531aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
532aed8d94eSDimitry Andric  static constexpr auto __make_fmatrix_impl(index_sequence<_Is...>,
533aed8d94eSDimitry Andric                                            index_sequence<_Js...>,
534aed8d94eSDimitry Andric                                            _Ls... __ls) {
535aed8d94eSDimitry Andric    return __base::__make_farray(__make_fmatrix_impl<_Fp, _Vs...>(
536aed8d94eSDimitry Andric        index_sequence<_Is..., _Js>{}, __ls...)...);
537aed8d94eSDimitry Andric  }
538aed8d94eSDimitry Andric
539aed8d94eSDimitry Andric  template <class _Fp, class... _Vs>
540aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
541aed8d94eSDimitry Andric  static constexpr auto __make_fmatrix() {
542aed8d94eSDimitry Andric    return __make_fmatrix_impl<_Fp, _Vs...>(
5434ba319b5SDimitry Andric        index_sequence<>{}, make_index_sequence<__uncvref_t<_Vs>::__size()>{}...);
544aed8d94eSDimitry Andric  }
545aed8d94eSDimitry Andric};
546aed8d94eSDimitry Andric
547aed8d94eSDimitry Andricstruct __variant {
548aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
549aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
550aed8d94eSDimitry Andric  static constexpr decltype(auto)
551aed8d94eSDimitry Andric  __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
552aed8d94eSDimitry Andric    return __base::__visit_alt_at(__index,
553aed8d94eSDimitry Andric                                  _VSTD::forward<_Visitor>(__visitor),
554aed8d94eSDimitry Andric                                  _VSTD::forward<_Vs>(__vs).__impl...);
555aed8d94eSDimitry Andric  }
556aed8d94eSDimitry Andric
557aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
558aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
559aed8d94eSDimitry Andric  static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor,
560aed8d94eSDimitry Andric                                              _Vs&&... __vs) {
561aed8d94eSDimitry Andric    return __base::__visit_alt(_VSTD::forward<_Visitor>(__visitor),
562aed8d94eSDimitry Andric                               _VSTD::forward<_Vs>(__vs).__impl...);
563aed8d94eSDimitry Andric  }
564aed8d94eSDimitry Andric
565aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
566aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
567aed8d94eSDimitry Andric  static constexpr decltype(auto)
568aed8d94eSDimitry Andric  __visit_value_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
569aed8d94eSDimitry Andric    return __visit_alt_at(
570aed8d94eSDimitry Andric        __index,
571aed8d94eSDimitry Andric        __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)),
572aed8d94eSDimitry Andric        _VSTD::forward<_Vs>(__vs)...);
573aed8d94eSDimitry Andric  }
574aed8d94eSDimitry Andric
575aed8d94eSDimitry Andric  template <class _Visitor, class... _Vs>
576aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
577aed8d94eSDimitry Andric  static constexpr decltype(auto) __visit_value(_Visitor&& __visitor,
578aed8d94eSDimitry Andric                                                _Vs&&... __vs) {
579aed8d94eSDimitry Andric    return __visit_alt(
580aed8d94eSDimitry Andric        __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)),
581aed8d94eSDimitry Andric        _VSTD::forward<_Vs>(__vs)...);
582aed8d94eSDimitry Andric  }
583aed8d94eSDimitry Andric
584aed8d94eSDimitry Andricprivate:
585aed8d94eSDimitry Andric  template <class _Visitor, class... _Values>
586aed8d94eSDimitry Andric  static constexpr void __std_visit_exhaustive_visitor_check() {
587b2c7081bSDimitry Andric    static_assert(is_invocable_v<_Visitor, _Values...>,
588aed8d94eSDimitry Andric                  "`std::visit` requires the visitor to be exhaustive.");
589aed8d94eSDimitry Andric  }
590aed8d94eSDimitry Andric
591aed8d94eSDimitry Andric  template <class _Visitor>
592aed8d94eSDimitry Andric  struct __value_visitor {
593aed8d94eSDimitry Andric    template <class... _Alts>
594aed8d94eSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY
595aed8d94eSDimitry Andric    constexpr decltype(auto) operator()(_Alts&&... __alts) const {
596aed8d94eSDimitry Andric      __std_visit_exhaustive_visitor_check<
597aed8d94eSDimitry Andric          _Visitor,
5985ca5951eSDimitry Andric          decltype((_VSTD::forward<_Alts>(__alts).__value))...>();
599aed8d94eSDimitry Andric      return __invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
600aed8d94eSDimitry Andric                                _VSTD::forward<_Alts>(__alts).__value...);
601aed8d94eSDimitry Andric    }
602aed8d94eSDimitry Andric    _Visitor&& __visitor;
603aed8d94eSDimitry Andric  };
604aed8d94eSDimitry Andric
605aed8d94eSDimitry Andric  template <class _Visitor>
606aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
607aed8d94eSDimitry Andric  static constexpr auto __make_value_visitor(_Visitor&& __visitor) {
608aed8d94eSDimitry Andric    return __value_visitor<_Visitor>{_VSTD::forward<_Visitor>(__visitor)};
609aed8d94eSDimitry Andric  }
610aed8d94eSDimitry Andric};
611aed8d94eSDimitry Andric
612aed8d94eSDimitry Andric} // namespace __visitation
613aed8d94eSDimitry Andric
614aed8d94eSDimitry Andrictemplate <size_t _Index, class _Tp>
615aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __alt {
616aed8d94eSDimitry Andric  using __value_type = _Tp;
617aed8d94eSDimitry Andric
618aed8d94eSDimitry Andric  template <class... _Args>
619aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
620aed8d94eSDimitry Andric  explicit constexpr __alt(in_place_t, _Args&&... __args)
621aed8d94eSDimitry Andric      : __value(_VSTD::forward<_Args>(__args)...) {}
622aed8d94eSDimitry Andric
623aed8d94eSDimitry Andric  __value_type __value;
624aed8d94eSDimitry Andric};
625aed8d94eSDimitry Andric
626aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, size_t _Index, class... _Types>
627aed8d94eSDimitry Andricunion _LIBCPP_TEMPLATE_VIS __union;
628aed8d94eSDimitry Andric
629aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, size_t _Index>
630aed8d94eSDimitry Andricunion _LIBCPP_TEMPLATE_VIS __union<_DestructibleTrait, _Index> {};
631aed8d94eSDimitry Andric
632aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_UNION(destructible_trait, destructor)                  \
633aed8d94eSDimitry Andric  template <size_t _Index, class _Tp, class... _Types>                         \
634aed8d94eSDimitry Andric  union _LIBCPP_TEMPLATE_VIS __union<destructible_trait,                      \
635aed8d94eSDimitry Andric                                      _Index,                                  \
636aed8d94eSDimitry Andric                                      _Tp,                                     \
637aed8d94eSDimitry Andric                                      _Types...> {                             \
638aed8d94eSDimitry Andric  public:                                                                      \
639aed8d94eSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY                                           \
640aed8d94eSDimitry Andric    explicit constexpr __union(__valueless_t) noexcept : __dummy{} {}          \
641aed8d94eSDimitry Andric                                                                               \
642aed8d94eSDimitry Andric    template <class... _Args>                                                  \
643aed8d94eSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY                                           \
644aed8d94eSDimitry Andric    explicit constexpr __union(in_place_index_t<0>, _Args&&... __args)         \
645aed8d94eSDimitry Andric        : __head(in_place, _VSTD::forward<_Args>(__args)...) {}                \
646aed8d94eSDimitry Andric                                                                               \
647aed8d94eSDimitry Andric    template <size_t _Ip, class... _Args>                                      \
648aed8d94eSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY                                           \
649aed8d94eSDimitry Andric    explicit constexpr __union(in_place_index_t<_Ip>, _Args&&... __args)       \
650aed8d94eSDimitry Andric        : __tail(in_place_index<_Ip - 1>, _VSTD::forward<_Args>(__args)...) {} \
651aed8d94eSDimitry Andric                                                                               \
652aed8d94eSDimitry Andric    __union(const __union&) = default;                                         \
653aed8d94eSDimitry Andric    __union(__union&&) = default;                                              \
654aed8d94eSDimitry Andric                                                                               \
655aed8d94eSDimitry Andric    destructor                                                                 \
656aed8d94eSDimitry Andric                                                                               \
657aed8d94eSDimitry Andric    __union& operator=(const __union&) = default;                              \
658aed8d94eSDimitry Andric    __union& operator=(__union&&) = default;                                   \
659aed8d94eSDimitry Andric                                                                               \
660aed8d94eSDimitry Andric  private:                                                                     \
661aed8d94eSDimitry Andric    char __dummy;                                                              \
662aed8d94eSDimitry Andric    __alt<_Index, _Tp> __head;                                                 \
663aed8d94eSDimitry Andric    __union<destructible_trait, _Index + 1, _Types...> __tail;                 \
664aed8d94eSDimitry Andric                                                                               \
665aed8d94eSDimitry Andric    friend struct __access::__union;                                           \
666aed8d94eSDimitry Andric  }
667aed8d94eSDimitry Andric
668aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_TriviallyAvailable, ~__union() = default;);
669aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_Available, ~__union() {});
670aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_Unavailable, ~__union() = delete;);
671aed8d94eSDimitry Andric
672aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_UNION
673aed8d94eSDimitry Andric
674aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, class... _Types>
675aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __base {
676aed8d94eSDimitry Andricpublic:
677b2c7081bSDimitry Andric  using __index_t = __variant_index_t<sizeof...(_Types)>;
678b2c7081bSDimitry Andric
679aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
680aed8d94eSDimitry Andric  explicit constexpr __base(__valueless_t tag) noexcept
681b2c7081bSDimitry Andric      : __data(tag), __index(__variant_npos<__index_t>) {}
682aed8d94eSDimitry Andric
683aed8d94eSDimitry Andric  template <size_t _Ip, class... _Args>
684aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
685aed8d94eSDimitry Andric  explicit constexpr __base(in_place_index_t<_Ip>, _Args&&... __args)
686aed8d94eSDimitry Andric      :
687aed8d94eSDimitry Andric        __data(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...),
688aed8d94eSDimitry Andric        __index(_Ip) {}
689aed8d94eSDimitry Andric
690aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
691aed8d94eSDimitry Andric  constexpr bool valueless_by_exception() const noexcept {
692aed8d94eSDimitry Andric    return index() == variant_npos;
693aed8d94eSDimitry Andric  }
694aed8d94eSDimitry Andric
695aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
696aed8d94eSDimitry Andric  constexpr size_t index() const noexcept {
697b2c7081bSDimitry Andric    return __index == __variant_npos<__index_t> ? variant_npos : __index;
698aed8d94eSDimitry Andric  }
699aed8d94eSDimitry Andric
700aed8d94eSDimitry Andricprotected:
701aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
702aed8d94eSDimitry Andric  constexpr auto&& __as_base() & { return *this; }
703aed8d94eSDimitry Andric
704aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
705aed8d94eSDimitry Andric  constexpr auto&& __as_base() && { return _VSTD::move(*this); }
706aed8d94eSDimitry Andric
707aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
708aed8d94eSDimitry Andric  constexpr auto&& __as_base() const & { return *this; }
709aed8d94eSDimitry Andric
710aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
711aed8d94eSDimitry Andric  constexpr auto&& __as_base() const && { return _VSTD::move(*this); }
712aed8d94eSDimitry Andric
713aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
714aed8d94eSDimitry Andric  static constexpr size_t __size() { return sizeof...(_Types); }
715aed8d94eSDimitry Andric
716aed8d94eSDimitry Andric  __union<_DestructibleTrait, 0, _Types...> __data;
717b2c7081bSDimitry Andric  __index_t __index;
718aed8d94eSDimitry Andric
719aed8d94eSDimitry Andric  friend struct __access::__base;
720aed8d94eSDimitry Andric  friend struct __visitation::__base;
721aed8d94eSDimitry Andric};
722aed8d94eSDimitry Andric
723aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__destructible_trait>
724aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __destructor;
725aed8d94eSDimitry Andric
726aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_DESTRUCTOR(destructible_trait, destructor, destroy)    \
727aed8d94eSDimitry Andric  template <class... _Types>                                                   \
728aed8d94eSDimitry Andric  class _LIBCPP_TEMPLATE_VIS __destructor<__traits<_Types...>,                 \
729aed8d94eSDimitry Andric                                           destructible_trait>                 \
730aed8d94eSDimitry Andric      : public __base<destructible_trait, _Types...> {                         \
731aed8d94eSDimitry Andric    using __base_type = __base<destructible_trait, _Types...>;                 \
732b2c7081bSDimitry Andric    using __index_t = typename __base_type::__index_t;                         \
733aed8d94eSDimitry Andric                                                                               \
734aed8d94eSDimitry Andric  public:                                                                      \
735aed8d94eSDimitry Andric    using __base_type::__base_type;                                            \
736aed8d94eSDimitry Andric    using __base_type::operator=;                                              \
737aed8d94eSDimitry Andric                                                                               \
738aed8d94eSDimitry Andric    __destructor(const __destructor&) = default;                               \
739aed8d94eSDimitry Andric    __destructor(__destructor&&) = default;                                    \
740aed8d94eSDimitry Andric    destructor                                                                 \
741aed8d94eSDimitry Andric    __destructor& operator=(const __destructor&) = default;                    \
742aed8d94eSDimitry Andric    __destructor& operator=(__destructor&&) = default;                         \
743aed8d94eSDimitry Andric                                                                               \
744aed8d94eSDimitry Andric  protected:                                                                   \
745aed8d94eSDimitry Andric    inline _LIBCPP_INLINE_VISIBILITY                                           \
746aed8d94eSDimitry Andric    destroy                                                                    \
747aed8d94eSDimitry Andric  }
748aed8d94eSDimitry Andric
749aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR(
750aed8d94eSDimitry Andric    _Trait::_TriviallyAvailable,
751aed8d94eSDimitry Andric    ~__destructor() = default;,
752b2c7081bSDimitry Andric    void __destroy() noexcept { this->__index = __variant_npos<__index_t>; });
753aed8d94eSDimitry Andric
754aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR(
755aed8d94eSDimitry Andric    _Trait::_Available,
756aed8d94eSDimitry Andric    ~__destructor() { __destroy(); },
757aed8d94eSDimitry Andric    void __destroy() noexcept {
758aed8d94eSDimitry Andric      if (!this->valueless_by_exception()) {
759aed8d94eSDimitry Andric        __visitation::__base::__visit_alt(
760aed8d94eSDimitry Andric            [](auto& __alt) noexcept {
7614ba319b5SDimitry Andric              using __alt_type = __uncvref_t<decltype(__alt)>;
762aed8d94eSDimitry Andric              __alt.~__alt_type();
763aed8d94eSDimitry Andric            },
764aed8d94eSDimitry Andric            *this);
765aed8d94eSDimitry Andric      }
766b2c7081bSDimitry Andric      this->__index = __variant_npos<__index_t>;
767aed8d94eSDimitry Andric    });
768aed8d94eSDimitry Andric
769aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR(
770aed8d94eSDimitry Andric    _Trait::_Unavailable,
771aed8d94eSDimitry Andric    ~__destructor() = delete;,
772aed8d94eSDimitry Andric    void __destroy() noexcept = delete;);
773aed8d94eSDimitry Andric
774aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_DESTRUCTOR
775aed8d94eSDimitry Andric
776aed8d94eSDimitry Andrictemplate <class _Traits>
777aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __constructor : public __destructor<_Traits> {
778aed8d94eSDimitry Andric  using __base_type = __destructor<_Traits>;
779aed8d94eSDimitry Andric
780aed8d94eSDimitry Andricpublic:
781aed8d94eSDimitry Andric  using __base_type::__base_type;
782aed8d94eSDimitry Andric  using __base_type::operator=;
783aed8d94eSDimitry Andric
784aed8d94eSDimitry Andricprotected:
785aed8d94eSDimitry Andric  template <size_t _Ip, class _Tp, class... _Args>
786aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
787540d2a8bSDimitry Andric  static _Tp& __construct_alt(__alt<_Ip, _Tp>& __a, _Args&&... __args) {
788540d2a8bSDimitry Andric    ::new ((void*)_VSTD::addressof(__a))
789aed8d94eSDimitry Andric        __alt<_Ip, _Tp>(in_place, _VSTD::forward<_Args>(__args)...);
790540d2a8bSDimitry Andric    return __a.__value;
791aed8d94eSDimitry Andric  }
792aed8d94eSDimitry Andric
793aed8d94eSDimitry Andric  template <class _Rhs>
794aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
795aed8d94eSDimitry Andric  static void __generic_construct(__constructor& __lhs, _Rhs&& __rhs) {
796aed8d94eSDimitry Andric    __lhs.__destroy();
797aed8d94eSDimitry Andric    if (!__rhs.valueless_by_exception()) {
798aed8d94eSDimitry Andric      __visitation::__base::__visit_alt_at(
799aed8d94eSDimitry Andric          __rhs.index(),
800aed8d94eSDimitry Andric          [](auto& __lhs_alt, auto&& __rhs_alt) {
801aed8d94eSDimitry Andric            __construct_alt(
802aed8d94eSDimitry Andric                __lhs_alt,
803aed8d94eSDimitry Andric                _VSTD::forward<decltype(__rhs_alt)>(__rhs_alt).__value);
804aed8d94eSDimitry Andric          },
805aed8d94eSDimitry Andric          __lhs, _VSTD::forward<_Rhs>(__rhs));
806aed8d94eSDimitry Andric      __lhs.__index = __rhs.index();
807aed8d94eSDimitry Andric    }
808aed8d94eSDimitry Andric  }
809aed8d94eSDimitry Andric};
810aed8d94eSDimitry Andric
811aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__move_constructible_trait>
812aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __move_constructor;
813aed8d94eSDimitry Andric
814aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait,             \
815aed8d94eSDimitry Andric                                         move_constructor)                     \
816aed8d94eSDimitry Andric  template <class... _Types>                                                   \
817aed8d94eSDimitry Andric  class _LIBCPP_TEMPLATE_VIS __move_constructor<__traits<_Types...>,          \
818aed8d94eSDimitry Andric                                                 move_constructible_trait>     \
819aed8d94eSDimitry Andric      : public __constructor<__traits<_Types...>> {                            \
820aed8d94eSDimitry Andric    using __base_type = __constructor<__traits<_Types...>>;                    \
821aed8d94eSDimitry Andric                                                                               \
822aed8d94eSDimitry Andric  public:                                                                      \
823aed8d94eSDimitry Andric    using __base_type::__base_type;                                            \
824aed8d94eSDimitry Andric    using __base_type::operator=;                                              \
825aed8d94eSDimitry Andric                                                                               \
826aed8d94eSDimitry Andric    __move_constructor(const __move_constructor&) = default;                   \
827aed8d94eSDimitry Andric    move_constructor                                                           \
828aed8d94eSDimitry Andric    ~__move_constructor() = default;                                           \
829aed8d94eSDimitry Andric    __move_constructor& operator=(const __move_constructor&) = default;        \
830aed8d94eSDimitry Andric    __move_constructor& operator=(__move_constructor&&) = default;             \
831aed8d94eSDimitry Andric  }
832aed8d94eSDimitry Andric
833aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
834aed8d94eSDimitry Andric    _Trait::_TriviallyAvailable,
835aed8d94eSDimitry Andric    __move_constructor(__move_constructor&& __that) = default;);
836aed8d94eSDimitry Andric
837aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
838aed8d94eSDimitry Andric    _Trait::_Available,
839aed8d94eSDimitry Andric    __move_constructor(__move_constructor&& __that) noexcept(
840aed8d94eSDimitry Andric        __all<is_nothrow_move_constructible_v<_Types>...>::value)
841aed8d94eSDimitry Andric        : __move_constructor(__valueless_t{}) {
842aed8d94eSDimitry Andric      this->__generic_construct(*this, _VSTD::move(__that));
843aed8d94eSDimitry Andric    });
844aed8d94eSDimitry Andric
845aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
846aed8d94eSDimitry Andric    _Trait::_Unavailable,
847aed8d94eSDimitry Andric    __move_constructor(__move_constructor&&) = delete;);
848aed8d94eSDimitry Andric
849aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_MOVE_CONSTRUCTOR
850aed8d94eSDimitry Andric
851aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__copy_constructible_trait>
852aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __copy_constructor;
853aed8d94eSDimitry Andric
854aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait,             \
855aed8d94eSDimitry Andric                                         copy_constructor)                     \
856aed8d94eSDimitry Andric  template <class... _Types>                                                   \
857aed8d94eSDimitry Andric  class _LIBCPP_TEMPLATE_VIS __copy_constructor<__traits<_Types...>,          \
858aed8d94eSDimitry Andric                                                 copy_constructible_trait>     \
859aed8d94eSDimitry Andric      : public __move_constructor<__traits<_Types...>> {                       \
860aed8d94eSDimitry Andric    using __base_type = __move_constructor<__traits<_Types...>>;               \
861aed8d94eSDimitry Andric                                                                               \
862aed8d94eSDimitry Andric  public:                                                                      \
863aed8d94eSDimitry Andric    using __base_type::__base_type;                                            \
864aed8d94eSDimitry Andric    using __base_type::operator=;                                              \
865aed8d94eSDimitry Andric                                                                               \
866aed8d94eSDimitry Andric    copy_constructor                                                           \
867aed8d94eSDimitry Andric    __copy_constructor(__copy_constructor&&) = default;                        \
868aed8d94eSDimitry Andric    ~__copy_constructor() = default;                                           \
869aed8d94eSDimitry Andric    __copy_constructor& operator=(const __copy_constructor&) = default;        \
870aed8d94eSDimitry Andric    __copy_constructor& operator=(__copy_constructor&&) = default;             \
871aed8d94eSDimitry Andric  }
872aed8d94eSDimitry Andric
873aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
874aed8d94eSDimitry Andric    _Trait::_TriviallyAvailable,
875aed8d94eSDimitry Andric    __copy_constructor(const __copy_constructor& __that) = default;);
876aed8d94eSDimitry Andric
877aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
878aed8d94eSDimitry Andric    _Trait::_Available,
879aed8d94eSDimitry Andric    __copy_constructor(const __copy_constructor& __that)
880aed8d94eSDimitry Andric        : __copy_constructor(__valueless_t{}) {
881aed8d94eSDimitry Andric      this->__generic_construct(*this, __that);
882aed8d94eSDimitry Andric    });
883aed8d94eSDimitry Andric
884aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
885aed8d94eSDimitry Andric    _Trait::_Unavailable,
886aed8d94eSDimitry Andric    __copy_constructor(const __copy_constructor&) = delete;);
887aed8d94eSDimitry Andric
888aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_COPY_CONSTRUCTOR
889aed8d94eSDimitry Andric
890aed8d94eSDimitry Andrictemplate <class _Traits>
891aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __assignment : public __copy_constructor<_Traits> {
892aed8d94eSDimitry Andric  using __base_type = __copy_constructor<_Traits>;
893aed8d94eSDimitry Andric
894aed8d94eSDimitry Andricpublic:
895aed8d94eSDimitry Andric  using __base_type::__base_type;
896aed8d94eSDimitry Andric  using __base_type::operator=;
897aed8d94eSDimitry Andric
898aed8d94eSDimitry Andric  template <size_t _Ip, class... _Args>
899aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
900540d2a8bSDimitry Andric  auto& __emplace(_Args&&... __args) {
901aed8d94eSDimitry Andric    this->__destroy();
902540d2a8bSDimitry Andric    auto& __res = this->__construct_alt(__access::__base::__get_alt<_Ip>(*this),
903aed8d94eSDimitry Andric                          _VSTD::forward<_Args>(__args)...);
904aed8d94eSDimitry Andric    this->__index = _Ip;
905540d2a8bSDimitry Andric    return __res;
906aed8d94eSDimitry Andric  }
907aed8d94eSDimitry Andric
908aed8d94eSDimitry Andricprotected:
909db17bf38SDimitry Andric  template <size_t _Ip, class _Tp, class _Arg>
910aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
911db17bf38SDimitry Andric  void __assign_alt(__alt<_Ip, _Tp>& __a, _Arg&& __arg) {
912aed8d94eSDimitry Andric    if (this->index() == _Ip) {
913aed8d94eSDimitry Andric      __a.__value = _VSTD::forward<_Arg>(__arg);
914aed8d94eSDimitry Andric    } else {
915aed8d94eSDimitry Andric      struct {
916aed8d94eSDimitry Andric        void operator()(true_type) const {
917db17bf38SDimitry Andric          __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg));
918aed8d94eSDimitry Andric        }
919aed8d94eSDimitry Andric        void operator()(false_type) const {
920db17bf38SDimitry Andric          __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg)));
921aed8d94eSDimitry Andric        }
922aed8d94eSDimitry Andric        __assignment* __this;
923aed8d94eSDimitry Andric        _Arg&& __arg;
924aed8d94eSDimitry Andric      } __impl{this, _VSTD::forward<_Arg>(__arg)};
925db17bf38SDimitry Andric      __impl(bool_constant<is_nothrow_constructible_v<_Tp, _Arg> ||
926db17bf38SDimitry Andric                           !is_nothrow_move_constructible_v<_Tp>>{});
927aed8d94eSDimitry Andric    }
928aed8d94eSDimitry Andric  }
929aed8d94eSDimitry Andric
930aed8d94eSDimitry Andric  template <class _That>
931aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
932aed8d94eSDimitry Andric  void __generic_assign(_That&& __that) {
933aed8d94eSDimitry Andric    if (this->valueless_by_exception() && __that.valueless_by_exception()) {
934aed8d94eSDimitry Andric      // do nothing.
935aed8d94eSDimitry Andric    } else if (__that.valueless_by_exception()) {
936aed8d94eSDimitry Andric      this->__destroy();
937aed8d94eSDimitry Andric    } else {
938aed8d94eSDimitry Andric      __visitation::__base::__visit_alt_at(
939aed8d94eSDimitry Andric          __that.index(),
940aed8d94eSDimitry Andric          [this](auto& __this_alt, auto&& __that_alt) {
941aed8d94eSDimitry Andric            this->__assign_alt(
942aed8d94eSDimitry Andric                __this_alt,
943db17bf38SDimitry Andric                _VSTD::forward<decltype(__that_alt)>(__that_alt).__value);
944aed8d94eSDimitry Andric          },
945aed8d94eSDimitry Andric          *this, _VSTD::forward<_That>(__that));
946aed8d94eSDimitry Andric    }
947aed8d94eSDimitry Andric  }
948aed8d94eSDimitry Andric};
949aed8d94eSDimitry Andric
950aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__move_assignable_trait>
951aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __move_assignment;
952aed8d94eSDimitry Andric
953aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait,                 \
954aed8d94eSDimitry Andric                                        move_assignment)                       \
955aed8d94eSDimitry Andric  template <class... _Types>                                                   \
956aed8d94eSDimitry Andric  class _LIBCPP_TEMPLATE_VIS __move_assignment<__traits<_Types...>,           \
957aed8d94eSDimitry Andric                                                move_assignable_trait>         \
958aed8d94eSDimitry Andric      : public __assignment<__traits<_Types...>> {                             \
959aed8d94eSDimitry Andric    using __base_type = __assignment<__traits<_Types...>>;                     \
960aed8d94eSDimitry Andric                                                                               \
961aed8d94eSDimitry Andric  public:                                                                      \
962aed8d94eSDimitry Andric    using __base_type::__base_type;                                            \
963aed8d94eSDimitry Andric    using __base_type::operator=;                                              \
964aed8d94eSDimitry Andric                                                                               \
965aed8d94eSDimitry Andric    __move_assignment(const __move_assignment&) = default;                     \
966aed8d94eSDimitry Andric    __move_assignment(__move_assignment&&) = default;                          \
967aed8d94eSDimitry Andric    ~__move_assignment() = default;                                            \
968aed8d94eSDimitry Andric    __move_assignment& operator=(const __move_assignment&) = default;          \
969aed8d94eSDimitry Andric    move_assignment                                                            \
970aed8d94eSDimitry Andric  }
971aed8d94eSDimitry Andric
972aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
973aed8d94eSDimitry Andric    _Trait::_TriviallyAvailable,
974aed8d94eSDimitry Andric    __move_assignment& operator=(__move_assignment&& __that) = default;);
975aed8d94eSDimitry Andric
976aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
977aed8d94eSDimitry Andric    _Trait::_Available,
978aed8d94eSDimitry Andric    __move_assignment& operator=(__move_assignment&& __that) noexcept(
979aed8d94eSDimitry Andric        __all<(is_nothrow_move_constructible_v<_Types> &&
980aed8d94eSDimitry Andric               is_nothrow_move_assignable_v<_Types>)...>::value) {
981aed8d94eSDimitry Andric      this->__generic_assign(_VSTD::move(__that));
982aed8d94eSDimitry Andric      return *this;
983aed8d94eSDimitry Andric    });
984aed8d94eSDimitry Andric
985aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
986aed8d94eSDimitry Andric    _Trait::_Unavailable,
987aed8d94eSDimitry Andric    __move_assignment& operator=(__move_assignment&&) = delete;);
988aed8d94eSDimitry Andric
989aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_MOVE_ASSIGNMENT
990aed8d94eSDimitry Andric
991aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__copy_assignable_trait>
992aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __copy_assignment;
993aed8d94eSDimitry Andric
994aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait,                 \
995aed8d94eSDimitry Andric                                        copy_assignment)                       \
996aed8d94eSDimitry Andric  template <class... _Types>                                                   \
997aed8d94eSDimitry Andric  class _LIBCPP_TEMPLATE_VIS __copy_assignment<__traits<_Types...>,           \
998aed8d94eSDimitry Andric                                                copy_assignable_trait>         \
999aed8d94eSDimitry Andric      : public __move_assignment<__traits<_Types...>> {                        \
1000aed8d94eSDimitry Andric    using __base_type = __move_assignment<__traits<_Types...>>;                \
1001aed8d94eSDimitry Andric                                                                               \
1002aed8d94eSDimitry Andric  public:                                                                      \
1003aed8d94eSDimitry Andric    using __base_type::__base_type;                                            \
1004aed8d94eSDimitry Andric    using __base_type::operator=;                                              \
1005aed8d94eSDimitry Andric                                                                               \
1006aed8d94eSDimitry Andric    __copy_assignment(const __copy_assignment&) = default;                     \
1007aed8d94eSDimitry Andric    __copy_assignment(__copy_assignment&&) = default;                          \
1008aed8d94eSDimitry Andric    ~__copy_assignment() = default;                                            \
1009aed8d94eSDimitry Andric    copy_assignment                                                            \
1010aed8d94eSDimitry Andric    __copy_assignment& operator=(__copy_assignment&&) = default;               \
1011aed8d94eSDimitry Andric  }
1012aed8d94eSDimitry Andric
1013aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1014aed8d94eSDimitry Andric    _Trait::_TriviallyAvailable,
1015aed8d94eSDimitry Andric    __copy_assignment& operator=(const __copy_assignment& __that) = default;);
1016aed8d94eSDimitry Andric
1017aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1018aed8d94eSDimitry Andric    _Trait::_Available,
1019aed8d94eSDimitry Andric    __copy_assignment& operator=(const __copy_assignment& __that) {
1020aed8d94eSDimitry Andric      this->__generic_assign(__that);
1021aed8d94eSDimitry Andric      return *this;
1022aed8d94eSDimitry Andric    });
1023aed8d94eSDimitry Andric
1024aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1025aed8d94eSDimitry Andric    _Trait::_Unavailable,
1026aed8d94eSDimitry Andric    __copy_assignment& operator=(const __copy_assignment&) = delete;);
1027aed8d94eSDimitry Andric
1028aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_COPY_ASSIGNMENT
1029aed8d94eSDimitry Andric
1030aed8d94eSDimitry Andrictemplate <class... _Types>
1031aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __impl
1032aed8d94eSDimitry Andric    : public __copy_assignment<__traits<_Types...>> {
1033aed8d94eSDimitry Andric  using __base_type = __copy_assignment<__traits<_Types...>>;
1034aed8d94eSDimitry Andric
1035aed8d94eSDimitry Andricpublic:
1036aed8d94eSDimitry Andric  using __base_type::__base_type;
1037aed8d94eSDimitry Andric  using __base_type::operator=;
1038aed8d94eSDimitry Andric
1039aed8d94eSDimitry Andric  template <size_t _Ip, class _Arg>
1040aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1041aed8d94eSDimitry Andric  void __assign(_Arg&& __arg) {
1042aed8d94eSDimitry Andric    this->__assign_alt(__access::__base::__get_alt<_Ip>(*this),
1043db17bf38SDimitry Andric                       _VSTD::forward<_Arg>(__arg));
1044aed8d94eSDimitry Andric  }
1045aed8d94eSDimitry Andric
1046aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1047aed8d94eSDimitry Andric  void __swap(__impl& __that)  {
1048aed8d94eSDimitry Andric    if (this->valueless_by_exception() && __that.valueless_by_exception()) {
1049aed8d94eSDimitry Andric      // do nothing.
1050aed8d94eSDimitry Andric    } else if (this->index() == __that.index()) {
1051aed8d94eSDimitry Andric      __visitation::__base::__visit_alt_at(
1052aed8d94eSDimitry Andric          this->index(),
1053aed8d94eSDimitry Andric          [](auto& __this_alt, auto& __that_alt) {
1054aed8d94eSDimitry Andric            using _VSTD::swap;
1055aed8d94eSDimitry Andric            swap(__this_alt.__value, __that_alt.__value);
1056aed8d94eSDimitry Andric          },
1057aed8d94eSDimitry Andric          *this,
1058aed8d94eSDimitry Andric          __that);
1059aed8d94eSDimitry Andric    } else {
1060aed8d94eSDimitry Andric      __impl* __lhs = this;
1061aed8d94eSDimitry Andric      __impl* __rhs = _VSTD::addressof(__that);
1062aed8d94eSDimitry Andric      if (__lhs->__move_nothrow() && !__rhs->__move_nothrow()) {
1063aed8d94eSDimitry Andric        _VSTD::swap(__lhs, __rhs);
1064aed8d94eSDimitry Andric      }
1065aed8d94eSDimitry Andric      __impl __tmp(_VSTD::move(*__rhs));
1066aed8d94eSDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS
1067aed8d94eSDimitry Andric      // EXTENSION: When the move construction of `__lhs` into `__rhs` throws
1068aed8d94eSDimitry Andric      // and `__tmp` is nothrow move constructible then we move `__tmp` back
1069*b5893f02SDimitry Andric      // into `__rhs` and provide the strong exception safety guarantee.
1070aed8d94eSDimitry Andric      try {
1071aed8d94eSDimitry Andric        this->__generic_construct(*__rhs, _VSTD::move(*__lhs));
1072aed8d94eSDimitry Andric      } catch (...) {
1073aed8d94eSDimitry Andric        if (__tmp.__move_nothrow()) {
1074aed8d94eSDimitry Andric          this->__generic_construct(*__rhs, _VSTD::move(__tmp));
1075aed8d94eSDimitry Andric        }
1076aed8d94eSDimitry Andric        throw;
1077aed8d94eSDimitry Andric      }
1078aed8d94eSDimitry Andric#else
1079aed8d94eSDimitry Andric      this->__generic_construct(*__rhs, _VSTD::move(*__lhs));
1080aed8d94eSDimitry Andric#endif
1081aed8d94eSDimitry Andric      this->__generic_construct(*__lhs, _VSTD::move(__tmp));
1082aed8d94eSDimitry Andric    }
1083aed8d94eSDimitry Andric  }
1084aed8d94eSDimitry Andric
1085aed8d94eSDimitry Andricprivate:
1086aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1087aed8d94eSDimitry Andric  bool __move_nothrow() const {
1088aed8d94eSDimitry Andric    constexpr bool __results[] = {is_nothrow_move_constructible_v<_Types>...};
1089aed8d94eSDimitry Andric    return this->valueless_by_exception() || __results[this->index()];
1090aed8d94eSDimitry Andric  }
1091aed8d94eSDimitry Andric};
1092aed8d94eSDimitry Andric
1093aed8d94eSDimitry Andrictemplate <class... _Types>
1094aed8d94eSDimitry Andricstruct __overload;
1095aed8d94eSDimitry Andric
1096aed8d94eSDimitry Andrictemplate <>
1097aed8d94eSDimitry Andricstruct __overload<> { void operator()() const; };
1098aed8d94eSDimitry Andric
1099aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1100aed8d94eSDimitry Andricstruct __overload<_Tp, _Types...> : __overload<_Types...> {
1101aed8d94eSDimitry Andric  using __overload<_Types...>::operator();
1102aed8d94eSDimitry Andric  __identity<_Tp> operator()(_Tp) const;
1103aed8d94eSDimitry Andric};
1104aed8d94eSDimitry Andric
1105aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1106aed8d94eSDimitry Andricusing __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type;
1107aed8d94eSDimitry Andric
1108aed8d94eSDimitry Andric} // __variant_detail
1109aed8d94eSDimitry Andric
1110aed8d94eSDimitry Andrictemplate <class... _Types>
1111aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS variant
1112aed8d94eSDimitry Andric    : private __sfinae_ctor_base<
1113aed8d94eSDimitry Andric          __all<is_copy_constructible_v<_Types>...>::value,
1114aed8d94eSDimitry Andric          __all<is_move_constructible_v<_Types>...>::value>,
1115aed8d94eSDimitry Andric      private __sfinae_assign_base<
1116aed8d94eSDimitry Andric          __all<(is_copy_constructible_v<_Types> &&
1117aed8d94eSDimitry Andric                 is_copy_assignable_v<_Types>)...>::value,
1118aed8d94eSDimitry Andric          __all<(is_move_constructible_v<_Types> &&
1119aed8d94eSDimitry Andric                 is_move_assignable_v<_Types>)...>::value> {
1120aed8d94eSDimitry Andric  static_assert(0 < sizeof...(_Types),
1121aed8d94eSDimitry Andric                "variant must consist of at least one alternative.");
1122aed8d94eSDimitry Andric
1123aed8d94eSDimitry Andric  static_assert(__all<!is_array_v<_Types>...>::value,
1124aed8d94eSDimitry Andric                "variant can not have an array type as an alternative.");
1125aed8d94eSDimitry Andric
1126aed8d94eSDimitry Andric  static_assert(__all<!is_reference_v<_Types>...>::value,
1127aed8d94eSDimitry Andric                "variant can not have a reference type as an alternative.");
1128aed8d94eSDimitry Andric
1129aed8d94eSDimitry Andric  static_assert(__all<!is_void_v<_Types>...>::value,
1130aed8d94eSDimitry Andric                "variant can not have a void type as an alternative.");
1131aed8d94eSDimitry Andric
1132aed8d94eSDimitry Andric  using __first_type = variant_alternative_t<0, variant>;
1133aed8d94eSDimitry Andric
1134aed8d94eSDimitry Andricpublic:
1135aed8d94eSDimitry Andric  template <bool _Dummy = true,
1136aed8d94eSDimitry Andric            enable_if_t<__dependent_type<is_default_constructible<__first_type>,
1137aed8d94eSDimitry Andric                                         _Dummy>::value,
1138aed8d94eSDimitry Andric                        int> = 0>
1139aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1140aed8d94eSDimitry Andric  constexpr variant() noexcept(is_nothrow_default_constructible_v<__first_type>)
1141aed8d94eSDimitry Andric      : __impl(in_place_index<0>) {}
1142aed8d94eSDimitry Andric
1143aed8d94eSDimitry Andric  variant(const variant&) = default;
1144aed8d94eSDimitry Andric  variant(variant&&) = default;
1145aed8d94eSDimitry Andric
1146aed8d94eSDimitry Andric  template <
1147aed8d94eSDimitry Andric      class _Arg,
11484ba319b5SDimitry Andric      enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0,
11494ba319b5SDimitry Andric      enable_if_t<!__is_inplace_type<__uncvref_t<_Arg>>::value, int> = 0,
11504ba319b5SDimitry Andric      enable_if_t<!__is_inplace_index<__uncvref_t<_Arg>>::value, int> = 0,
1151aed8d94eSDimitry Andric      class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
1152aed8d94eSDimitry Andric      size_t _Ip =
1153aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1154aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0>
1155aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1156aed8d94eSDimitry Andric  constexpr variant(_Arg&& __arg) noexcept(
1157aed8d94eSDimitry Andric      is_nothrow_constructible_v<_Tp, _Arg>)
1158aed8d94eSDimitry Andric      : __impl(in_place_index<_Ip>, _VSTD::forward<_Arg>(__arg)) {}
1159aed8d94eSDimitry Andric
1160aed8d94eSDimitry Andric  template <size_t _Ip, class... _Args,
11615517e702SDimitry Andric            class = enable_if_t<(_Ip < sizeof...(_Types)), int>,
1162aed8d94eSDimitry Andric            class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1163aed8d94eSDimitry Andric            enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1164aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1165aed8d94eSDimitry Andric  explicit constexpr variant(
1166aed8d94eSDimitry Andric      in_place_index_t<_Ip>,
1167aed8d94eSDimitry Andric      _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1168aed8d94eSDimitry Andric      : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {}
1169aed8d94eSDimitry Andric
1170aed8d94eSDimitry Andric  template <
1171aed8d94eSDimitry Andric      size_t _Ip,
1172aed8d94eSDimitry Andric      class _Up,
1173aed8d94eSDimitry Andric      class... _Args,
1174aed8d94eSDimitry Andric      enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1175aed8d94eSDimitry Andric      class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1176aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1177aed8d94eSDimitry Andric                  int> = 0>
1178aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1179aed8d94eSDimitry Andric  explicit constexpr variant(
1180aed8d94eSDimitry Andric      in_place_index_t<_Ip>,
1181aed8d94eSDimitry Andric      initializer_list<_Up> __il,
1182aed8d94eSDimitry Andric      _Args&&... __args) noexcept(
1183aed8d94eSDimitry Andric      is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
1184aed8d94eSDimitry Andric      : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {}
1185aed8d94eSDimitry Andric
1186aed8d94eSDimitry Andric  template <
1187aed8d94eSDimitry Andric      class _Tp,
1188aed8d94eSDimitry Andric      class... _Args,
1189aed8d94eSDimitry Andric      size_t _Ip =
1190aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1191aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1192aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1193aed8d94eSDimitry Andric  explicit constexpr variant(in_place_type_t<_Tp>, _Args&&... __args) noexcept(
1194aed8d94eSDimitry Andric      is_nothrow_constructible_v<_Tp, _Args...>)
1195aed8d94eSDimitry Andric      : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {}
1196aed8d94eSDimitry Andric
1197aed8d94eSDimitry Andric  template <
1198aed8d94eSDimitry Andric      class _Tp,
1199aed8d94eSDimitry Andric      class _Up,
1200aed8d94eSDimitry Andric      class... _Args,
1201aed8d94eSDimitry Andric      size_t _Ip =
1202aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1203aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1204aed8d94eSDimitry Andric                  int> = 0>
1205aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1206aed8d94eSDimitry Andric  explicit constexpr variant(
1207aed8d94eSDimitry Andric      in_place_type_t<_Tp>,
1208aed8d94eSDimitry Andric      initializer_list<_Up> __il,
1209aed8d94eSDimitry Andric      _Args&&... __args) noexcept(
1210aed8d94eSDimitry Andric      is_nothrow_constructible_v<_Tp, initializer_list< _Up>&, _Args...>)
1211aed8d94eSDimitry Andric      : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {}
1212aed8d94eSDimitry Andric
1213aed8d94eSDimitry Andric  ~variant() = default;
1214aed8d94eSDimitry Andric
1215aed8d94eSDimitry Andric  variant& operator=(const variant&) = default;
1216aed8d94eSDimitry Andric  variant& operator=(variant&&) = default;
1217aed8d94eSDimitry Andric
1218aed8d94eSDimitry Andric  template <
1219aed8d94eSDimitry Andric      class _Arg,
12204ba319b5SDimitry Andric      enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0,
1221aed8d94eSDimitry Andric      class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
1222aed8d94eSDimitry Andric      size_t _Ip =
1223aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1224aed8d94eSDimitry Andric      enable_if_t<is_assignable_v<_Tp&, _Arg> && is_constructible_v<_Tp, _Arg>,
1225aed8d94eSDimitry Andric                  int> = 0>
1226aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1227aed8d94eSDimitry Andric  variant& operator=(_Arg&& __arg) noexcept(
1228aed8d94eSDimitry Andric      is_nothrow_assignable_v<_Tp&, _Arg> &&
1229aed8d94eSDimitry Andric      is_nothrow_constructible_v<_Tp, _Arg>) {
1230aed8d94eSDimitry Andric    __impl.template __assign<_Ip>(_VSTD::forward<_Arg>(__arg));
1231aed8d94eSDimitry Andric    return *this;
1232aed8d94eSDimitry Andric  }
1233aed8d94eSDimitry Andric
1234aed8d94eSDimitry Andric  template <
1235aed8d94eSDimitry Andric      size_t _Ip,
1236aed8d94eSDimitry Andric      class... _Args,
1237aed8d94eSDimitry Andric      enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1238aed8d94eSDimitry Andric      class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1239aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1240aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1241540d2a8bSDimitry Andric  _Tp& emplace(_Args&&... __args) {
1242540d2a8bSDimitry Andric    return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...);
1243aed8d94eSDimitry Andric  }
1244aed8d94eSDimitry Andric
1245aed8d94eSDimitry Andric  template <
1246aed8d94eSDimitry Andric      size_t _Ip,
1247aed8d94eSDimitry Andric      class _Up,
1248aed8d94eSDimitry Andric      class... _Args,
1249aed8d94eSDimitry Andric      enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1250aed8d94eSDimitry Andric      class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1251aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1252aed8d94eSDimitry Andric                  int> = 0>
1253aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1254540d2a8bSDimitry Andric  _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
1255540d2a8bSDimitry Andric    return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...);
1256aed8d94eSDimitry Andric  }
1257aed8d94eSDimitry Andric
1258aed8d94eSDimitry Andric  template <
1259aed8d94eSDimitry Andric      class _Tp,
1260aed8d94eSDimitry Andric      class... _Args,
1261aed8d94eSDimitry Andric      size_t _Ip =
1262aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1263aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1264aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1265540d2a8bSDimitry Andric  _Tp& emplace(_Args&&... __args) {
1266540d2a8bSDimitry Andric    return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...);
1267aed8d94eSDimitry Andric  }
1268aed8d94eSDimitry Andric
1269aed8d94eSDimitry Andric  template <
1270aed8d94eSDimitry Andric      class _Tp,
1271aed8d94eSDimitry Andric      class _Up,
1272aed8d94eSDimitry Andric      class... _Args,
1273aed8d94eSDimitry Andric      size_t _Ip =
1274aed8d94eSDimitry Andric          __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1275aed8d94eSDimitry Andric      enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1276aed8d94eSDimitry Andric                  int> = 0>
1277aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1278540d2a8bSDimitry Andric  _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
1279540d2a8bSDimitry Andric    return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...);
1280aed8d94eSDimitry Andric  }
1281aed8d94eSDimitry Andric
1282aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1283aed8d94eSDimitry Andric  constexpr bool valueless_by_exception() const noexcept {
1284aed8d94eSDimitry Andric    return __impl.valueless_by_exception();
1285aed8d94eSDimitry Andric  }
1286aed8d94eSDimitry Andric
1287aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1288aed8d94eSDimitry Andric  constexpr size_t index() const noexcept { return __impl.index(); }
1289aed8d94eSDimitry Andric
1290aed8d94eSDimitry Andric  template <
1291aed8d94eSDimitry Andric      bool _Dummy = true,
1292aed8d94eSDimitry Andric      enable_if_t<
1293aed8d94eSDimitry Andric          __all<(
1294aed8d94eSDimitry Andric              __dependent_type<is_move_constructible<_Types>, _Dummy>::value &&
1295aed8d94eSDimitry Andric              __dependent_type<is_swappable<_Types>, _Dummy>::value)...>::value,
1296aed8d94eSDimitry Andric          int> = 0>
1297aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1298aed8d94eSDimitry Andric  void swap(variant& __that) noexcept(
1299aed8d94eSDimitry Andric      __all<(is_nothrow_move_constructible_v<_Types> &&
1300aed8d94eSDimitry Andric             is_nothrow_swappable_v<_Types>)...>::value) {
1301aed8d94eSDimitry Andric    __impl.__swap(__that.__impl);
1302aed8d94eSDimitry Andric  }
1303aed8d94eSDimitry Andric
1304aed8d94eSDimitry Andricprivate:
1305aed8d94eSDimitry Andric  __variant_detail::__impl<_Types...> __impl;
1306aed8d94eSDimitry Andric
1307aed8d94eSDimitry Andric  friend struct __variant_detail::__access::__variant;
1308aed8d94eSDimitry Andric  friend struct __variant_detail::__visitation::__variant;
1309aed8d94eSDimitry Andric};
1310aed8d94eSDimitry Andric
1311aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1312aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1313aed8d94eSDimitry Andricconstexpr bool __holds_alternative(const variant<_Types...>& __v) noexcept {
1314aed8d94eSDimitry Andric  return __v.index() == _Ip;
1315aed8d94eSDimitry Andric}
1316aed8d94eSDimitry Andric
1317aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1318aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1319aed8d94eSDimitry Andricconstexpr bool holds_alternative(const variant<_Types...>& __v) noexcept {
1320aed8d94eSDimitry Andric  return __holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1321aed8d94eSDimitry Andric}
1322aed8d94eSDimitry Andric
1323aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Vp>
1324aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1325*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1326*b5893f02SDimitry Andricconstexpr auto&& __generic_get(_Vp&& __v) {
1327aed8d94eSDimitry Andric  using __variant_detail::__access::__variant;
1328aed8d94eSDimitry Andric  if (!__holds_alternative<_Ip>(__v)) {
1329aed8d94eSDimitry Andric    __throw_bad_variant_access();
1330aed8d94eSDimitry Andric  }
1331aed8d94eSDimitry Andric  return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value;
1332aed8d94eSDimitry Andric}
1333aed8d94eSDimitry Andric
1334aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1335aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1336*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1337aed8d94eSDimitry Andricconstexpr variant_alternative_t<_Ip, variant<_Types...>>& get(
1338aed8d94eSDimitry Andric    variant<_Types...>& __v) {
1339aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1340aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1341aed8d94eSDimitry Andric  return __generic_get<_Ip>(__v);
1342aed8d94eSDimitry Andric}
1343aed8d94eSDimitry Andric
1344aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1345aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1346*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1347aed8d94eSDimitry Andricconstexpr variant_alternative_t<_Ip, variant<_Types...>>&& get(
1348aed8d94eSDimitry Andric    variant<_Types...>&& __v) {
1349aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1350aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1351aed8d94eSDimitry Andric  return __generic_get<_Ip>(_VSTD::move(__v));
1352aed8d94eSDimitry Andric}
1353aed8d94eSDimitry Andric
1354aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1355aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1356*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1357aed8d94eSDimitry Andricconstexpr const variant_alternative_t<_Ip, variant<_Types...>>& get(
1358aed8d94eSDimitry Andric    const variant<_Types...>& __v) {
1359aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1360aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1361aed8d94eSDimitry Andric  return __generic_get<_Ip>(__v);
1362aed8d94eSDimitry Andric}
1363aed8d94eSDimitry Andric
1364aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1365aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1366*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1367aed8d94eSDimitry Andricconstexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get(
1368aed8d94eSDimitry Andric    const variant<_Types...>&& __v) {
1369aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1370aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1371aed8d94eSDimitry Andric  return __generic_get<_Ip>(_VSTD::move(__v));
1372aed8d94eSDimitry Andric}
1373aed8d94eSDimitry Andric
1374aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1375aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1376*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1377aed8d94eSDimitry Andricconstexpr _Tp& get(variant<_Types...>& __v) {
1378aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1379aed8d94eSDimitry Andric  return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1380aed8d94eSDimitry Andric}
1381aed8d94eSDimitry Andric
1382aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1383aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1384*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1385aed8d94eSDimitry Andricconstexpr _Tp&& get(variant<_Types...>&& __v) {
1386aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1387aed8d94eSDimitry Andric  return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(
1388aed8d94eSDimitry Andric      _VSTD::move(__v));
1389aed8d94eSDimitry Andric}
1390aed8d94eSDimitry Andric
1391aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1392aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1393*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1394aed8d94eSDimitry Andricconstexpr const _Tp& get(const variant<_Types...>& __v) {
1395aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1396aed8d94eSDimitry Andric  return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1397aed8d94eSDimitry Andric}
1398aed8d94eSDimitry Andric
1399aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1400aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1401*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1402aed8d94eSDimitry Andricconstexpr const _Tp&& get(const variant<_Types...>&& __v) {
1403aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1404aed8d94eSDimitry Andric  return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(
1405aed8d94eSDimitry Andric      _VSTD::move(__v));
1406aed8d94eSDimitry Andric}
1407aed8d94eSDimitry Andric
1408aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Vp>
1409aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1410aed8d94eSDimitry Andricconstexpr auto* __generic_get_if(_Vp* __v) noexcept {
1411aed8d94eSDimitry Andric  using __variant_detail::__access::__variant;
1412aed8d94eSDimitry Andric  return __v && __holds_alternative<_Ip>(*__v)
1413aed8d94eSDimitry Andric             ? _VSTD::addressof(__variant::__get_alt<_Ip>(*__v).__value)
1414aed8d94eSDimitry Andric             : nullptr;
1415aed8d94eSDimitry Andric}
1416aed8d94eSDimitry Andric
1417aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1418aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1419aed8d94eSDimitry Andricconstexpr add_pointer_t<variant_alternative_t<_Ip, variant<_Types...>>>
1420aed8d94eSDimitry Andricget_if(variant<_Types...>* __v) noexcept {
1421aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1422aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1423aed8d94eSDimitry Andric  return __generic_get_if<_Ip>(__v);
1424aed8d94eSDimitry Andric}
1425aed8d94eSDimitry Andric
1426aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types>
1427aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1428aed8d94eSDimitry Andricconstexpr add_pointer_t<const variant_alternative_t<_Ip, variant<_Types...>>>
1429aed8d94eSDimitry Andricget_if(const variant<_Types...>* __v) noexcept {
1430aed8d94eSDimitry Andric  static_assert(_Ip < sizeof...(_Types));
1431aed8d94eSDimitry Andric  static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1432aed8d94eSDimitry Andric  return __generic_get_if<_Ip>(__v);
1433aed8d94eSDimitry Andric}
1434aed8d94eSDimitry Andric
1435aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1436aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1437aed8d94eSDimitry Andricconstexpr add_pointer_t<_Tp>
1438aed8d94eSDimitry Andricget_if(variant<_Types...>* __v) noexcept {
1439aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1440aed8d94eSDimitry Andric  return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1441aed8d94eSDimitry Andric}
1442aed8d94eSDimitry Andric
1443aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types>
1444aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1445aed8d94eSDimitry Andricconstexpr add_pointer_t<const _Tp>
1446aed8d94eSDimitry Andricget_if(const variant<_Types...>* __v) noexcept {
1447aed8d94eSDimitry Andric  static_assert(!is_void_v<_Tp>);
1448aed8d94eSDimitry Andric  return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1449aed8d94eSDimitry Andric}
1450aed8d94eSDimitry Andric
1451*b5893f02SDimitry Andrictemplate <class _Operator>
1452*b5893f02SDimitry Andricstruct __convert_to_bool {
1453*b5893f02SDimitry Andric  template <class _T1, class _T2>
1454*b5893f02SDimitry Andric  _LIBCPP_INLINE_VISIBILITY constexpr bool operator()(_T1 && __t1, _T2&& __t2) const {
1455*b5893f02SDimitry Andric    static_assert(std::is_convertible<decltype(_Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2))), bool>::value,
1456*b5893f02SDimitry Andric        "the relational operator does not return a type which is implicitly convertible to bool");
1457*b5893f02SDimitry Andric    return _Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2));
1458*b5893f02SDimitry Andric  }
1459*b5893f02SDimitry Andric};
1460*b5893f02SDimitry Andric
1461aed8d94eSDimitry Andrictemplate <class... _Types>
1462aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1463aed8d94eSDimitry Andricconstexpr bool operator==(const variant<_Types...>& __lhs,
1464aed8d94eSDimitry Andric                          const variant<_Types...>& __rhs) {
1465aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1466aed8d94eSDimitry Andric  if (__lhs.index() != __rhs.index()) return false;
1467aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return true;
1468*b5893f02SDimitry Andric  return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<equal_to<>>{}, __lhs, __rhs);
1469aed8d94eSDimitry Andric}
1470aed8d94eSDimitry Andric
1471aed8d94eSDimitry Andrictemplate <class... _Types>
1472aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1473aed8d94eSDimitry Andricconstexpr bool operator!=(const variant<_Types...>& __lhs,
1474aed8d94eSDimitry Andric                          const variant<_Types...>& __rhs) {
1475aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1476aed8d94eSDimitry Andric  if (__lhs.index() != __rhs.index()) return true;
1477aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return false;
1478aed8d94eSDimitry Andric  return __variant::__visit_value_at(
1479*b5893f02SDimitry Andric      __lhs.index(), __convert_to_bool<not_equal_to<>>{}, __lhs, __rhs);
1480aed8d94eSDimitry Andric}
1481aed8d94eSDimitry Andric
1482aed8d94eSDimitry Andrictemplate <class... _Types>
1483aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1484aed8d94eSDimitry Andricconstexpr bool operator<(const variant<_Types...>& __lhs,
1485aed8d94eSDimitry Andric                         const variant<_Types...>& __rhs) {
1486aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1487aed8d94eSDimitry Andric  if (__rhs.valueless_by_exception()) return false;
1488aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return true;
1489aed8d94eSDimitry Andric  if (__lhs.index() < __rhs.index()) return true;
1490aed8d94eSDimitry Andric  if (__lhs.index() > __rhs.index()) return false;
1491*b5893f02SDimitry Andric  return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<less<>>{}, __lhs, __rhs);
1492aed8d94eSDimitry Andric}
1493aed8d94eSDimitry Andric
1494aed8d94eSDimitry Andrictemplate <class... _Types>
1495aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1496aed8d94eSDimitry Andricconstexpr bool operator>(const variant<_Types...>& __lhs,
1497aed8d94eSDimitry Andric                         const variant<_Types...>& __rhs) {
1498aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1499aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return false;
1500aed8d94eSDimitry Andric  if (__rhs.valueless_by_exception()) return true;
1501aed8d94eSDimitry Andric  if (__lhs.index() > __rhs.index()) return true;
1502aed8d94eSDimitry Andric  if (__lhs.index() < __rhs.index()) return false;
1503*b5893f02SDimitry Andric  return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<greater<>>{}, __lhs, __rhs);
1504aed8d94eSDimitry Andric}
1505aed8d94eSDimitry Andric
1506aed8d94eSDimitry Andrictemplate <class... _Types>
1507aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1508aed8d94eSDimitry Andricconstexpr bool operator<=(const variant<_Types...>& __lhs,
1509aed8d94eSDimitry Andric                          const variant<_Types...>& __rhs) {
1510aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1511aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return true;
1512aed8d94eSDimitry Andric  if (__rhs.valueless_by_exception()) return false;
1513aed8d94eSDimitry Andric  if (__lhs.index() < __rhs.index()) return true;
1514aed8d94eSDimitry Andric  if (__lhs.index() > __rhs.index()) return false;
1515aed8d94eSDimitry Andric  return __variant::__visit_value_at(
1516*b5893f02SDimitry Andric      __lhs.index(), __convert_to_bool<less_equal<>>{}, __lhs, __rhs);
1517aed8d94eSDimitry Andric}
1518aed8d94eSDimitry Andric
1519aed8d94eSDimitry Andrictemplate <class... _Types>
1520aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1521aed8d94eSDimitry Andricconstexpr bool operator>=(const variant<_Types...>& __lhs,
1522aed8d94eSDimitry Andric                          const variant<_Types...>& __rhs) {
1523aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1524aed8d94eSDimitry Andric  if (__rhs.valueless_by_exception()) return true;
1525aed8d94eSDimitry Andric  if (__lhs.valueless_by_exception()) return false;
1526aed8d94eSDimitry Andric  if (__lhs.index() > __rhs.index()) return true;
1527aed8d94eSDimitry Andric  if (__lhs.index() < __rhs.index()) return false;
1528aed8d94eSDimitry Andric  return __variant::__visit_value_at(
1529*b5893f02SDimitry Andric      __lhs.index(), __convert_to_bool<greater_equal<>>{}, __lhs, __rhs);
1530aed8d94eSDimitry Andric}
1531aed8d94eSDimitry Andric
1532aed8d94eSDimitry Andrictemplate <class _Visitor, class... _Vs>
1533aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1534*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
1535aed8d94eSDimitry Andricconstexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) {
1536aed8d94eSDimitry Andric  using __variant_detail::__visitation::__variant;
1537aed8d94eSDimitry Andric  bool __results[] = {__vs.valueless_by_exception()...};
1538aed8d94eSDimitry Andric  for (bool __result : __results) {
1539aed8d94eSDimitry Andric    if (__result) {
1540aed8d94eSDimitry Andric      __throw_bad_variant_access();
1541aed8d94eSDimitry Andric    }
1542aed8d94eSDimitry Andric  }
1543aed8d94eSDimitry Andric  return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor),
1544aed8d94eSDimitry Andric                                  _VSTD::forward<_Vs>(__vs)...);
1545aed8d94eSDimitry Andric}
1546aed8d94eSDimitry Andric
1547aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS monostate {};
1548aed8d94eSDimitry Andric
1549aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1550aed8d94eSDimitry Andricconstexpr bool operator<(monostate, monostate) noexcept { return false; }
1551aed8d94eSDimitry Andric
1552aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1553aed8d94eSDimitry Andricconstexpr bool operator>(monostate, monostate) noexcept { return false; }
1554aed8d94eSDimitry Andric
1555aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1556aed8d94eSDimitry Andricconstexpr bool operator<=(monostate, monostate) noexcept { return true; }
1557aed8d94eSDimitry Andric
1558aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1559aed8d94eSDimitry Andricconstexpr bool operator>=(monostate, monostate) noexcept { return true; }
1560aed8d94eSDimitry Andric
1561aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1562aed8d94eSDimitry Andricconstexpr bool operator==(monostate, monostate) noexcept { return true; }
1563aed8d94eSDimitry Andric
1564aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1565aed8d94eSDimitry Andricconstexpr bool operator!=(monostate, monostate) noexcept { return false; }
1566aed8d94eSDimitry Andric
1567aed8d94eSDimitry Andrictemplate <class... _Types>
1568aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1569aed8d94eSDimitry Andricauto swap(variant<_Types...>& __lhs,
1570aed8d94eSDimitry Andric          variant<_Types...>& __rhs) noexcept(noexcept(__lhs.swap(__rhs)))
1571aed8d94eSDimitry Andric    -> decltype(__lhs.swap(__rhs)) {
1572aed8d94eSDimitry Andric  __lhs.swap(__rhs);
1573aed8d94eSDimitry Andric}
1574aed8d94eSDimitry Andric
1575aed8d94eSDimitry Andrictemplate <class... _Types>
1576540d2a8bSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<
1577540d2a8bSDimitry Andric    __enable_hash_helper<variant<_Types...>, remove_const_t<_Types>...>> {
1578aed8d94eSDimitry Andric  using argument_type = variant<_Types...>;
1579aed8d94eSDimitry Andric  using result_type = size_t;
1580aed8d94eSDimitry Andric
1581aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1582aed8d94eSDimitry Andric  result_type operator()(const argument_type& __v) const {
1583aed8d94eSDimitry Andric    using __variant_detail::__visitation::__variant;
1584aed8d94eSDimitry Andric    size_t __res =
1585aed8d94eSDimitry Andric        __v.valueless_by_exception()
1586aed8d94eSDimitry Andric               ? 299792458 // Random value chosen by the universe upon creation
1587aed8d94eSDimitry Andric               : __variant::__visit_alt(
1588aed8d94eSDimitry Andric                     [](const auto& __alt) {
15894ba319b5SDimitry Andric                       using __alt_type = __uncvref_t<decltype(__alt)>;
1590540d2a8bSDimitry Andric                       using __value_type = remove_const_t<
1591540d2a8bSDimitry Andric                         typename __alt_type::__value_type>;
1592aed8d94eSDimitry Andric                       return hash<__value_type>{}(__alt.__value);
1593aed8d94eSDimitry Andric                     },
1594aed8d94eSDimitry Andric                     __v);
1595aed8d94eSDimitry Andric    return __hash_combine(__res, hash<size_t>{}(__v.index()));
1596aed8d94eSDimitry Andric  }
1597aed8d94eSDimitry Andric};
1598aed8d94eSDimitry Andric
1599aed8d94eSDimitry Andrictemplate <>
1600aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<monostate> {
1601aed8d94eSDimitry Andric  using argument_type = monostate;
1602aed8d94eSDimitry Andric  using result_type = size_t;
1603aed8d94eSDimitry Andric
1604aed8d94eSDimitry Andric  inline _LIBCPP_INLINE_VISIBILITY
1605540d2a8bSDimitry Andric  result_type operator()(const argument_type&) const _NOEXCEPT {
1606aed8d94eSDimitry Andric    return 66740831; // return a fundamentally attractive random value.
1607aed8d94eSDimitry Andric  }
1608aed8d94eSDimitry Andric};
1609aed8d94eSDimitry Andric
1610aed8d94eSDimitry Andric#endif  // _LIBCPP_STD_VER > 14
1611aed8d94eSDimitry Andric
1612aed8d94eSDimitry Andric_LIBCPP_END_NAMESPACE_STD
1613aed8d94eSDimitry Andric
1614b2c7081bSDimitry Andric_LIBCPP_POP_MACROS
1615b2c7081bSDimitry Andric
1616aed8d94eSDimitry Andric#endif  // _LIBCPP_VARIANT
1617