]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/variant
Add __raw_visit and __raw_idx_visit, use INVOKE<R>
[thirdparty/gcc.git] / libstdc++-v3 / include / std / variant
CommitLineData
85adbce1 1// <variant> -*- C++ -*-
2
fbd26352 3// Copyright (C) 2016-2019 Free Software Foundation, Inc.
85adbce1 4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file variant
26 * This is the <variant> C++ Library header.
27 */
28
29#ifndef _GLIBCXX_VARIANT
30#define _GLIBCXX_VARIANT 1
31
32#pragma GCC system_header
33
a9e86108 34#if __cplusplus >= 201703L
85adbce1 35
36#include <type_traits>
37#include <utility>
38#include <bits/enable_special_members.h>
d923797a 39#include <bits/functexcept.h>
4b3b2026 40#include <bits/move.h>
17515fad 41#include <bits/functional_hash.h>
2a5d61f9 42#include <bits/invoke.h>
caaaa8fd 43#include <ext/aligned_buffer.h>
cfdb4aba 44#include <bits/parse_numbers.h>
ae8365d5 45#include <bits/stl_iterator_base_types.h>
46#include <bits/stl_iterator_base_funcs.h>
47#include <bits/stl_construct.h>
85adbce1 48
49namespace std _GLIBCXX_VISIBILITY(default)
50{
ae6a4ce9 51_GLIBCXX_BEGIN_NAMESPACE_VERSION
52
2a5d61f9 53namespace __detail
54{
55namespace __variant
56{
2a5d61f9 57 template<size_t _Np, typename... _Types>
58 struct _Nth_type;
59
60 template<size_t _Np, typename _First, typename... _Rest>
61 struct _Nth_type<_Np, _First, _Rest...>
62 : _Nth_type<_Np-1, _Rest...> { };
63
64 template<typename _First, typename... _Rest>
65 struct _Nth_type<0, _First, _Rest...>
66 { using type = _First; };
67
2a5d61f9 68} // namespace __variant
69} // namespace __detail
70
d253bcb1 71#define __cpp_lib_variant 201606L
a9e86108 72
85adbce1 73 template<typename... _Types> class tuple;
74 template<typename... _Types> class variant;
75 template <typename> struct hash;
76
77 template<typename _Variant>
78 struct variant_size;
79
80 template<typename _Variant>
81 struct variant_size<const _Variant> : variant_size<_Variant> {};
82
83 template<typename _Variant>
84 struct variant_size<volatile _Variant> : variant_size<_Variant> {};
85
86 template<typename _Variant>
87 struct variant_size<const volatile _Variant> : variant_size<_Variant> {};
88
89 template<typename... _Types>
90 struct variant_size<variant<_Types...>>
91 : std::integral_constant<size_t, sizeof...(_Types)> {};
92
93 template<typename _Variant>
b5492afc 94 inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
85adbce1 95
96 template<size_t _Np, typename _Variant>
97 struct variant_alternative;
98
99 template<size_t _Np, typename _First, typename... _Rest>
100 struct variant_alternative<_Np, variant<_First, _Rest...>>
101 : variant_alternative<_Np-1, variant<_Rest...>> {};
102
103 template<typename _First, typename... _Rest>
104 struct variant_alternative<0, variant<_First, _Rest...>>
105 { using type = _First; };
106
107 template<size_t _Np, typename _Variant>
108 using variant_alternative_t =
109 typename variant_alternative<_Np, _Variant>::type;
110
909ccf61 111 template<size_t _Np, typename _Variant>
112 struct variant_alternative<_Np, const _Variant>
113 { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; };
114
115 template<size_t _Np, typename _Variant>
116 struct variant_alternative<_Np, volatile _Variant>
117 { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; };
118
119 template<size_t _Np, typename _Variant>
120 struct variant_alternative<_Np, const volatile _Variant>
121 { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; };
122
b5492afc 123 inline constexpr size_t variant_npos = -1;
85adbce1 124
2a5d61f9 125 template<size_t _Np, typename... _Types>
126 constexpr variant_alternative_t<_Np, variant<_Types...>>&
127 get(variant<_Types...>&);
128
129 template<size_t _Np, typename... _Types>
130 constexpr variant_alternative_t<_Np, variant<_Types...>>&&
131 get(variant<_Types...>&&);
132
133 template<size_t _Np, typename... _Types>
134 constexpr variant_alternative_t<_Np, variant<_Types...>> const&
135 get(const variant<_Types...>&);
136
137 template<size_t _Np, typename... _Types>
138 constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
139 get(const variant<_Types...>&&);
140
f03f26fa 141 template<typename _Result_type, typename _Visitor, typename... _Variants>
49c83dca 142 constexpr decltype(auto)
143 __do_visit(_Visitor&& __visitor, _Variants&&... __variants);
144
145 template <typename... _Types, typename _Tp>
492debfa 146 decltype(auto)
147 __variant_cast(_Tp&& __rhs)
49c83dca 148 {
149 if constexpr (is_lvalue_reference_v<_Tp>)
150 {
151 if constexpr (is_const_v<remove_reference_t<_Tp>>)
152 return static_cast<const variant<_Types...>&>(__rhs);
153 else
154 return static_cast<variant<_Types...>&>(__rhs);
155 }
156 else
157 return static_cast<variant<_Types...>&&>(__rhs);
158 }
159
85adbce1 160namespace __detail
161{
162namespace __variant
163{
164 // Returns the first apparence of _Tp in _Types.
165 // Returns sizeof...(_Types) if _Tp is not in _Types.
166 template<typename _Tp, typename... _Types>
167 struct __index_of : std::integral_constant<size_t, 0> {};
168
169 template<typename _Tp, typename... _Types>
b5492afc 170 inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value;
85adbce1 171
172 template<typename _Tp, typename _First, typename... _Rest>
173 struct __index_of<_Tp, _First, _Rest...> :
174 std::integral_constant<size_t, is_same_v<_Tp, _First>
175 ? 0 : __index_of_v<_Tp, _Rest...> + 1> {};
176
49c83dca 177 // used for raw visitation
178 struct __variant_cookie {};
4f3e024d 179 // used for raw visitation with indices passed in
47cf9c4c 180 struct __variant_idx_cookie { using type = __variant_idx_cookie; };
f03f26fa 181 // Used to enable deduction (and same-type checking) for std::visit:
182 template<typename> struct __deduce_visit_result { };
183
184 // Visit variants that might be valueless.
185 template<typename _Visitor, typename... _Variants>
186 constexpr void
187 __raw_visit(_Visitor&& __visitor, _Variants&&... __variants)
188 {
189 std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor),
190 std::forward<_Variants>(__variants)...);
191 }
192
193 // Visit variants that might be valueless, passing indices to the visitor.
194 template<typename _Visitor, typename... _Variants>
195 constexpr void
196 __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants)
197 {
198 std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor),
199 std::forward<_Variants>(__variants)...);
200 }
49c83dca 201
caaaa8fd 202 // _Uninitialized<T> is guaranteed to be a literal type, even if T is not.
203 // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented
204 // yet. When it's implemented, _Uninitialized<T> can be changed to the alias
205 // to T, therefore equivalent to being removed entirely.
206 //
207 // Another reason we may not want to remove _Uninitialzied<T> may be that, we
208 // want _Uninitialized<T> to be trivially destructible, no matter whether T
209 // is; but we will see.
210 template<typename _Type, bool = std::is_literal_type_v<_Type>>
85adbce1 211 struct _Uninitialized;
212
213 template<typename _Type>
214 struct _Uninitialized<_Type, true>
215 {
85adbce1 216 template<typename... _Args>
492debfa 217 constexpr
218 _Uninitialized(in_place_index_t<0>, _Args&&... __args)
219 : _M_storage(std::forward<_Args>(__args)...)
220 { }
85adbce1 221
e11f5aed 222 constexpr const _Type& _M_get() const & noexcept
caaaa8fd 223 { return _M_storage; }
224
e11f5aed 225 constexpr _Type& _M_get() & noexcept
caaaa8fd 226 { return _M_storage; }
227
e11f5aed 228 constexpr const _Type&& _M_get() const && noexcept
caaaa8fd 229 { return std::move(_M_storage); }
230
e11f5aed 231 constexpr _Type&& _M_get() && noexcept
caaaa8fd 232 { return std::move(_M_storage); }
233
85adbce1 234 _Type _M_storage;
235 };
236
237 template<typename _Type>
238 struct _Uninitialized<_Type, false>
239 {
85adbce1 240 template<typename... _Args>
492debfa 241 constexpr
242 _Uninitialized(in_place_index_t<0>, _Args&&... __args)
243 {
244 ::new ((void*)std::addressof(_M_storage))
245 _Type(std::forward<_Args>(__args)...);
246 }
85adbce1 247
e11f5aed 248 const _Type& _M_get() const & noexcept
caaaa8fd 249 { return *_M_storage._M_ptr(); }
250
e11f5aed 251 _Type& _M_get() & noexcept
caaaa8fd 252 { return *_M_storage._M_ptr(); }
253
e11f5aed 254 const _Type&& _M_get() const && noexcept
caaaa8fd 255 { return std::move(*_M_storage._M_ptr()); }
256
e11f5aed 257 _Type&& _M_get() && noexcept
caaaa8fd 258 { return std::move(*_M_storage._M_ptr()); }
259
260 __gnu_cxx::__aligned_membuf<_Type> _M_storage;
85adbce1 261 };
262
caaaa8fd 263 template<typename _Union>
e11f5aed 264 constexpr decltype(auto)
265 __get(in_place_index_t<0>, _Union&& __u) noexcept
caaaa8fd 266 { return std::forward<_Union>(__u)._M_first._M_get(); }
267
268 template<size_t _Np, typename _Union>
e11f5aed 269 constexpr decltype(auto)
270 __get(in_place_index_t<_Np>, _Union&& __u) noexcept
a8f8d460 271 {
272 return __variant::__get(in_place_index<_Np-1>,
273 std::forward<_Union>(__u)._M_rest);
274 }
caaaa8fd 275
276 // Returns the typed storage for __v.
277 template<size_t _Np, typename _Variant>
e11f5aed 278 constexpr decltype(auto)
279 __get(_Variant&& __v) noexcept
caaaa8fd 280 {
a8f8d460 281 return __variant::__get(std::in_place_index<_Np>,
282 std::forward<_Variant>(__v)._M_u);
caaaa8fd 283 }
284
77c62063 285 template<typename... _Types>
286 struct _Traits
287 {
288 static constexpr bool _S_default_ctor =
ae6a4ce9 289 is_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
77c62063 290 static constexpr bool _S_copy_ctor =
ae6a4ce9 291 (is_copy_constructible_v<_Types> && ...);
77c62063 292 static constexpr bool _S_move_ctor =
ae6a4ce9 293 (is_move_constructible_v<_Types> && ...);
77c62063 294 static constexpr bool _S_copy_assign =
37a7dbf9 295 _S_copy_ctor
ae6a4ce9 296 && (is_copy_assignable_v<_Types> && ...);
77c62063 297 static constexpr bool _S_move_assign =
ae6a4ce9 298 _S_move_ctor
299 && (is_move_assignable_v<_Types> && ...);
77c62063 300
301 static constexpr bool _S_trivial_dtor =
ae6a4ce9 302 (is_trivially_destructible_v<_Types> && ...);
77c62063 303 static constexpr bool _S_trivial_copy_ctor =
ae6a4ce9 304 (is_trivially_copy_constructible_v<_Types> && ...);
77c62063 305 static constexpr bool _S_trivial_move_ctor =
ae6a4ce9 306 (is_trivially_move_constructible_v<_Types> && ...);
77c62063 307 static constexpr bool _S_trivial_copy_assign =
a4265b66 308 _S_trivial_dtor && _S_trivial_copy_ctor
309 && (is_trivially_copy_assignable_v<_Types> && ...);
77c62063 310 static constexpr bool _S_trivial_move_assign =
a4265b66 311 _S_trivial_dtor && _S_trivial_move_ctor
312 && (is_trivially_move_assignable_v<_Types> && ...);
77c62063 313
314 // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
315 // are always nothrow.
316 static constexpr bool _S_nothrow_default_ctor =
ae6a4ce9 317 is_nothrow_default_constructible_v<
318 typename _Nth_type<0, _Types...>::type>;
77c62063 319 static constexpr bool _S_nothrow_copy_ctor = false;
320 static constexpr bool _S_nothrow_move_ctor =
ae6a4ce9 321 (is_nothrow_move_constructible_v<_Types> && ...);
77c62063 322 static constexpr bool _S_nothrow_copy_assign = false;
323 static constexpr bool _S_nothrow_move_assign =
a4265b66 324 _S_nothrow_move_ctor
325 && (is_nothrow_move_assignable_v<_Types> && ...);
77c62063 326 };
327
caaaa8fd 328 // Defines members and ctors.
85adbce1 329 template<typename... _Types>
caaaa8fd 330 union _Variadic_union { };
85adbce1 331
85adbce1 332 template<typename _First, typename... _Rest>
caaaa8fd 333 union _Variadic_union<_First, _Rest...>
85adbce1 334 {
caaaa8fd 335 constexpr _Variadic_union() : _M_rest() { }
336
337 template<typename... _Args>
338 constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args)
339 : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
340 { }
341
342 template<size_t _Np, typename... _Args>
343 constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
344 : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
345 { }
346
347 _Uninitialized<_First> _M_first;
348 _Variadic_union<_Rest...> _M_rest;
349 };
350
781cb64d 351 // _Never_valueless_alt is true for variant alternatives that can
352 // always be placed in a variant without it becoming valueless.
353
354 // For suitably-small, trivially copyable types we can create temporaries
355 // on the stack and then memcpy them into place.
356 template<typename _Tp>
357 struct _Never_valueless_alt
358 : __and_<bool_constant<sizeof(_Tp) <= 256>, is_trivially_copyable<_Tp>>
359 { };
360
361 // Specialize _Never_valueless_alt for other types which have a
b9d8292f 362 // non-throwing and cheap move construction and move assignment operator,
363 // so that emplacing the type will provide the strong exception-safety
364 // guarantee, by creating and moving a temporary.
781cb64d 365 // Whether _Never_valueless_alt<T> is true or not affects the ABI of a
366 // variant using that alternative, so we can't change the value later!
367
368 // True if every alternative in _Types... can be emplaced in a variant
369 // without it becoming valueless. If this is true, variant<_Types...>
370 // can never be valueless, which enables some minor optimizations.
4c0ef551 371 template <typename... _Types>
781cb64d 372 constexpr bool __never_valueless()
373 {
b9d8292f 374 return _Traits<_Types...>::_S_move_assign
375 && (_Never_valueless_alt<_Types>::value && ...);
781cb64d 376 }
4c0ef551 377
caaaa8fd 378 // Defines index and the dtor, possibly trivial.
379 template<bool __trivially_destructible, typename... _Types>
380 struct _Variant_storage;
381
cfdb4aba 382 template <typename... _Types>
492debfa 383 using __select_index =
384 typename __select_int::_Select_int_base<sizeof...(_Types),
385 unsigned char,
386 unsigned short>::type::value_type;
cfdb4aba 387
caaaa8fd 388 template<typename... _Types>
389 struct _Variant_storage<false, _Types...>
390 {
caaaa8fd 391 constexpr _Variant_storage() : _M_index(variant_npos) { }
85adbce1 392
56835b0d 393 template<size_t _Np, typename... _Args>
85adbce1 394 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
caaaa8fd 395 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
396 _M_index(_Np)
85adbce1 397 { }
398
49c83dca 399 constexpr void _M_reset_impl()
400 {
f03f26fa 401 __variant::__raw_visit([](auto&& __this_mem) mutable
49c83dca 402 {
403 if constexpr (!is_same_v<remove_reference_t<decltype(__this_mem)>,
404 __variant_cookie>)
405 std::_Destroy(std::__addressof(__this_mem));
49c83dca 406 }, __variant_cast<_Types...>(*this));
492debfa 407 }
85adbce1 408
a6787bda 409 void _M_reset()
410 {
49c83dca 411 _M_reset_impl();
a6787bda 412 _M_index = variant_npos;
413 }
414
caaaa8fd 415 ~_Variant_storage()
a6787bda 416 { _M_reset(); }
85adbce1 417
77c62063 418 void*
5c6334a5 419 _M_storage() const noexcept
77c62063 420 {
421 return const_cast<void*>(static_cast<const void*>(
422 std::addressof(_M_u)));
423 }
424
425 constexpr bool
426 _M_valid() const noexcept
427 {
b9d8292f 428 if constexpr (__never_valueless<_Types...>())
429 return true;
77c62063 430 return this->_M_index != __index_type(variant_npos);
431 }
432
caaaa8fd 433 _Variadic_union<_Types...> _M_u;
cfdb4aba 434 using __index_type = __select_index<_Types...>;
435 __index_type _M_index;
85adbce1 436 };
437
caaaa8fd 438 template<typename... _Types>
439 struct _Variant_storage<true, _Types...>
85adbce1 440 {
caaaa8fd 441 constexpr _Variant_storage() : _M_index(variant_npos) { }
85adbce1 442
caaaa8fd 443 template<size_t _Np, typename... _Args>
444 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
445 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
446 _M_index(_Np)
447 { }
448
5c6334a5 449 void _M_reset() noexcept
a6787bda 450 { _M_index = variant_npos; }
451
77c62063 452 void*
5c6334a5 453 _M_storage() const noexcept
77c62063 454 {
455 return const_cast<void*>(static_cast<const void*>(
456 std::addressof(_M_u)));
457 }
458
459 constexpr bool
460 _M_valid() const noexcept
461 {
4c0ef551 462 if constexpr (__never_valueless<_Types...>())
bc35ec6d 463 return true;
77c62063 464 return this->_M_index != __index_type(variant_npos);
465 }
466
caaaa8fd 467 _Variadic_union<_Types...> _M_u;
cfdb4aba 468 using __index_type = __select_index<_Types...>;
469 __index_type _M_index;
85adbce1 470 };
471
85adbce1 472 template<typename... _Types>
77c62063 473 using _Variant_storage_alias =
ae6a4ce9 474 _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
85adbce1 475
225ca87b 476 template<typename _Tp, typename _Up>
477 void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem)
478 {
479 void* __storage = std::addressof(__lhs._M_u);
480 using _Type = remove_reference_t<decltype(__rhs_mem)>;
481 if constexpr (!is_same_v<_Type, __variant_cookie>)
482 ::new (__storage)
483 _Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
484 }
485
49c83dca 486 template<typename... _Types, typename _Tp, typename _Up>
487 void __variant_construct(_Tp&& __lhs, _Up&& __rhs)
488 {
489 __lhs._M_index = __rhs._M_index;
f03f26fa 490 __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable
49c83dca 491 {
225ca87b 492 __variant_construct_single(std::forward<_Tp>(__lhs),
fd1863e1 493 std::forward<decltype(__rhs_mem)>(__rhs_mem));
fd1863e1 494 }, __variant_cast<_Types...>(std::forward<_Up>(__rhs)));
49c83dca 495 }
496
77c62063 497 // The following are (Copy|Move) (ctor|assign) layers for forwarding
498 // triviality and handling non-trivial SMF behaviors.
499
500 template<bool, typename... _Types>
501 struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
502 {
503 using _Base = _Variant_storage_alias<_Types...>;
504 using _Base::_Base;
85adbce1 505
77c62063 506 _Copy_ctor_base(const _Copy_ctor_base& __rhs)
ae6a4ce9 507 noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
85adbce1 508 {
49c83dca 509 __variant_construct<_Types...>(*this, __rhs);
85adbce1 510 }
511
77c62063 512 _Copy_ctor_base(_Copy_ctor_base&&) = default;
513 _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default;
514 _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default;
515 };
516
517 template<typename... _Types>
518 struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...>
519 {
520 using _Base = _Variant_storage_alias<_Types...>;
521 using _Base::_Base;
522 };
523
524 template<typename... _Types>
525 using _Copy_ctor_alias =
ae6a4ce9 526 _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>;
77c62063 527
528 template<bool, typename... _Types>
529 struct _Move_ctor_base : _Copy_ctor_alias<_Types...>
530 {
531 using _Base = _Copy_ctor_alias<_Types...>;
532 using _Base::_Base;
533
534 _Move_ctor_base(_Move_ctor_base&& __rhs)
ae6a4ce9 535 noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
85adbce1 536 {
fd1863e1 537 __variant_construct<_Types...>(*this, std::move(__rhs));
49c83dca 538 }
539
225ca87b 540 template<typename _Up>
541 void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
542 {
543 this->_M_reset();
fd1863e1 544 __variant_construct_single(*this, std::forward<_Up>(__rhs));
225ca87b 545 this->_M_index = __rhs_index;
225ca87b 546 }
85adbce1 547
225ca87b 548 template<typename _Up>
549 void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
550 {
551 this->_M_reset();
fd1863e1 552 __variant_construct_single(*this, __rhs);
225ca87b 553 this->_M_index = __rhs_index;
225ca87b 554 }
a4c655fb 555
77c62063 556 _Move_ctor_base(const _Move_ctor_base&) = default;
557 _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
558 _Move_ctor_base& operator=(_Move_ctor_base&&) = default;
559 };
560
561 template<typename... _Types>
562 struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...>
563 {
564 using _Base = _Copy_ctor_alias<_Types...>;
565 using _Base::_Base;
a4c655fb 566
225ca87b 567 template<typename _Up>
568 void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
569 {
570 this->_M_reset();
fd1863e1 571 __variant_construct_single(*this, std::forward<_Up>(__rhs));
225ca87b 572 this->_M_index = __rhs_index;
225ca87b 573 }
492debfa 574
225ca87b 575 template<typename _Up>
576 void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
577 {
578 this->_M_reset();
225ca87b 579 __variant_construct_single(*this, __rhs);
fd1863e1 580 this->_M_index = __rhs_index;
225ca87b 581 }
77c62063 582 };
583
584 template<typename... _Types>
585 using _Move_ctor_alias =
ae6a4ce9 586 _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>;
77c62063 587
588 template<bool, typename... _Types>
589 struct _Copy_assign_base : _Move_ctor_alias<_Types...>
590 {
591 using _Base = _Move_ctor_alias<_Types...>;
592 using _Base::_Base;
85adbce1 593
77c62063 594 _Copy_assign_base&
595 operator=(const _Copy_assign_base& __rhs)
ae6a4ce9 596 noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
85adbce1 597 {
f03f26fa 598 __variant::__raw_idx_visit(
599 [this](auto&& __rhs_mem, auto __rhs_index) mutable
85adbce1 600 {
4f3e024d 601 if constexpr (__rhs_index != variant_npos)
85adbce1 602 {
4f3e024d 603 if (this->_M_index == __rhs_index)
fd1863e1 604 __variant::__get<__rhs_index>(*this) = __rhs_mem;
4f3e024d 605 else
606 {
fd1863e1 607 using __rhs_type = __remove_cvref_t<decltype(__rhs_mem)>;
608 if constexpr (is_nothrow_copy_constructible_v<__rhs_type>
609 || !is_nothrow_move_constructible_v<__rhs_type>)
610 // The standard says this->emplace<__rhs_type>(__rhs_mem)
611 // should be used here, but _M_destructive_copy is
612 // equivalent in this case. Either copy construction
613 // doesn't throw, so _M_destructive_copy gives strong
614 // exception safety guarantee, or both copy construction
615 // and move construction can throw, so emplace only gives
616 // basic exception safety anyway.
617 this->_M_destructive_copy(__rhs_index, __rhs_mem);
49c83dca 618 else
fd1863e1 619 __variant_cast<_Types...>(*this)
620 = variant<_Types...>(__rhs_mem);
49c83dca 621 }
49c83dca 622 }
4f3e024d 623 else
624 this->_M_reset();
4f3e024d 625 }, __variant_cast<_Types...>(__rhs));
85adbce1 626 return *this;
627 }
628
77c62063 629 _Copy_assign_base(const _Copy_assign_base&) = default;
630 _Copy_assign_base(_Copy_assign_base&&) = default;
631 _Copy_assign_base& operator=(_Copy_assign_base&&) = default;
632 };
633
634 template<typename... _Types>
635 struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...>
636 {
637 using _Base = _Move_ctor_alias<_Types...>;
638 using _Base::_Base;
639 };
640
641 template<typename... _Types>
642 using _Copy_assign_alias =
a4265b66 643 _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>;
77c62063 644
645 template<bool, typename... _Types>
646 struct _Move_assign_base : _Copy_assign_alias<_Types...>
647 {
648 using _Base = _Copy_assign_alias<_Types...>;
649 using _Base::_Base;
650
77c62063 651 _Move_assign_base&
652 operator=(_Move_assign_base&& __rhs)
ae6a4ce9 653 noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
85adbce1 654 {
f03f26fa 655 __variant::__raw_idx_visit(
656 [this](auto&& __rhs_mem, auto __rhs_index) mutable
85adbce1 657 {
4f3e024d 658 if constexpr (__rhs_index != variant_npos)
85adbce1 659 {
4f3e024d 660 if (this->_M_index == __rhs_index)
fd1863e1 661 __variant::__get<__rhs_index>(*this) = std::move(__rhs_mem);
4f3e024d 662 else
fd1863e1 663 __variant_cast<_Types...>(*this)
664 .template emplace<__rhs_index>(std::move(__rhs_mem));
85adbce1 665 }
49c83dca 666 else
4f3e024d 667 this->_M_reset();
4f3e024d 668 }, __variant_cast<_Types...>(__rhs));
85adbce1 669 return *this;
670 }
671
77c62063 672 _Move_assign_base(const _Move_assign_base&) = default;
673 _Move_assign_base(_Move_assign_base&&) = default;
674 _Move_assign_base& operator=(const _Move_assign_base&) = default;
675 };
85adbce1 676
77c62063 677 template<typename... _Types>
678 struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...>
679 {
680 using _Base = _Copy_assign_alias<_Types...>;
681 using _Base::_Base;
682 };
683
684 template<typename... _Types>
685 using _Move_assign_alias =
492debfa 686 _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
77c62063 687
688 template<typename... _Types>
689 struct _Variant_base : _Move_assign_alias<_Types...>
690 {
691 using _Base = _Move_assign_alias<_Types...>;
692
693 constexpr
694 _Variant_base()
ae6a4ce9 695 noexcept(_Traits<_Types...>::_S_nothrow_default_ctor)
77c62063 696 : _Variant_base(in_place_index<0>) { }
697
698 template<size_t _Np, typename... _Args>
699 constexpr explicit
700 _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
701 : _Base(__i, std::forward<_Args>(__args)...)
702 { }
703
704 _Variant_base(const _Variant_base&) = default;
705 _Variant_base(_Variant_base&&) = default;
706 _Variant_base& operator=(const _Variant_base&) = default;
707 _Variant_base& operator=(_Variant_base&&) = default;
85adbce1 708 };
709
710 // For how many times does _Tp appear in _Tuple?
711 template<typename _Tp, typename _Tuple>
712 struct __tuple_count;
713
714 template<typename _Tp, typename _Tuple>
b5492afc 715 inline constexpr size_t __tuple_count_v =
716 __tuple_count<_Tp, _Tuple>::value;
85adbce1 717
718 template<typename _Tp, typename... _Types>
719 struct __tuple_count<_Tp, tuple<_Types...>>
720 : integral_constant<size_t, 0> { };
721
722 template<typename _Tp, typename _First, typename... _Rest>
723 struct __tuple_count<_Tp, tuple<_First, _Rest...>>
724 : integral_constant<
725 size_t,
726 __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { };
727
728 // TODO: Reuse this in <tuple> ?
729 template<typename _Tp, typename... _Types>
b5492afc 730 inline constexpr bool __exactly_once =
731 __tuple_count_v<_Tp, tuple<_Types...>> == 1;
85adbce1 732
733 // Takes _Types and create an overloaded _S_fun for each type.
734 // If a type appears more than once in _Types, create only one overload.
735 template<typename... _Types>
736 struct __overload_set
737 { static void _S_fun(); };
738
739 template<typename _First, typename... _Rest>
740 struct __overload_set<_First, _Rest...> : __overload_set<_Rest...>
741 {
742 using __overload_set<_Rest...>::_S_fun;
743 static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
744 };
745
746 template<typename... _Rest>
747 struct __overload_set<void, _Rest...> : __overload_set<_Rest...>
748 {
749 using __overload_set<_Rest...>::_S_fun;
750 };
751
752 // Helper for variant(_Tp&&) and variant::operator=(_Tp&&).
6dd97553 753 // __accepted_index maps an arbitrary _Tp to an alternative type in _Variant
754 // (or to variant_npos).
85adbce1 755 template<typename _Tp, typename _Variant, typename = void>
756 struct __accepted_index
757 { static constexpr size_t value = variant_npos; };
758
759 template<typename _Tp, typename... _Types>
760 struct __accepted_index<
761 _Tp, variant<_Types...>,
6dd97553 762 void_t<decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()))>>
85adbce1 763 {
764 static constexpr size_t value = sizeof...(_Types) - 1
765 - decltype(__overload_set<_Types...>::
766 _S_fun(std::declval<_Tp>()))::value;
767 };
768
769 // Returns the raw storage for __v.
770 template<typename _Variant>
5c6334a5 771 void* __get_storage(_Variant&& __v) noexcept
85adbce1 772 { return __v._M_storage(); }
773
4c0ef551 774 template <typename _Maybe_variant_cookie, typename _Variant>
781cb64d 775 struct _Extra_visit_slot_needed
776 {
777 template <typename> struct _Variant_never_valueless;
4c0ef551 778
781cb64d 779 template <typename... _Types>
780 struct _Variant_never_valueless<variant<_Types...>>
781 : bool_constant<__never_valueless<_Types...>()> {};
4c0ef551 782
781cb64d 783 static constexpr bool value =
784 (is_same_v<_Maybe_variant_cookie, __variant_cookie>
785 || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>)
786 && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value;
787 };
4c0ef551 788
492debfa 789 // Used for storing a multi-dimensional vtable.
85adbce1 790 template<typename _Tp, size_t... _Dimensions>
492debfa 791 struct _Multi_array;
792
793 // Partial specialization with rank zero, stores a single _Tp element.
794 template<typename _Tp>
795 struct _Multi_array<_Tp>
85adbce1 796 {
f03f26fa 797 template<typename>
798 struct __untag_result
799 : false_type
800 { using element_type = _Tp; };
801
802 template <typename... _Args>
803 struct __untag_result<const void(*)(_Args...)>
804 : false_type
805 { using element_type = void(*)(_Args...); };
806
807 template <typename... _Args>
808 struct __untag_result<__variant_cookie(*)(_Args...)>
809 : false_type
810 { using element_type = void(*)(_Args...); };
811
812 template <typename... _Args>
813 struct __untag_result<__variant_idx_cookie(*)(_Args...)>
814 : false_type
815 { using element_type = void(*)(_Args...); };
816
817 template <typename _Res, typename... _Args>
818 struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)>
819 : true_type
820 { using element_type = _Res(*)(_Args...); };
821
822 using __result_is_deduced = __untag_result<_Tp>;
823
824 constexpr const typename __untag_result<_Tp>::element_type&
85adbce1 825 _M_access() const
826 { return _M_data; }
827
f03f26fa 828 typename __untag_result<_Tp>::element_type _M_data;
85adbce1 829 };
830
492debfa 831 // Partial specialization with rank >= 1.
49c83dca 832 template<typename _Ret,
833 typename _Visitor,
834 typename... _Variants,
835 size_t __first, size_t... __rest>
836 struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...>
85adbce1 837 {
4c0ef551 838 static constexpr size_t __index =
839 sizeof...(_Variants) - sizeof...(__rest) - 1;
492debfa 840
4c0ef551 841 using _Variant = typename _Nth_type<__index, _Variants...>::type;
492debfa 842
49c83dca 843 static constexpr int __do_cookie =
4c0ef551 844 _Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0;
492debfa 845
49c83dca 846 using _Tp = _Ret(*)(_Visitor, _Variants...);
492debfa 847
85adbce1 848 template<typename... _Args>
f03f26fa 849 constexpr decltype(auto)
85adbce1 850 _M_access(size_t __first_index, _Args... __rest_indices) const
492debfa 851 {
852 return _M_arr[__first_index + __do_cookie]
853 ._M_access(__rest_indices...);
854 }
85adbce1 855
49c83dca 856 _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie];
85adbce1 857 };
858
859 // Creates a multi-dimensional vtable recursively.
85adbce1 860 //
861 // For example,
862 // visit([](auto, auto){},
2a5d61f9 863 // variant<int, char>(), // typedef'ed as V1
864 // variant<float, double, long double>()) // typedef'ed as V2
85adbce1 865 // will trigger instantiations of:
f03f26fa 866 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>,
2a5d61f9 867 // tuple<V1&&, V2&&>, std::index_sequence<>>
f03f26fa 868 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
2a5d61f9 869 // tuple<V1&&, V2&&>, std::index_sequence<0>>
f03f26fa 870 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 871 // tuple<V1&&, V2&&>, std::index_sequence<0, 0>>
f03f26fa 872 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 873 // tuple<V1&&, V2&&>, std::index_sequence<0, 1>>
f03f26fa 874 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 875 // tuple<V1&&, V2&&>, std::index_sequence<0, 2>>
f03f26fa 876 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
2a5d61f9 877 // tuple<V1&&, V2&&>, std::index_sequence<1>>
f03f26fa 878 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 879 // tuple<V1&&, V2&&>, std::index_sequence<1, 0>>
f03f26fa 880 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 881 // tuple<V1&&, V2&&>, std::index_sequence<1, 1>>
f03f26fa 882 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
2a5d61f9 883 // tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
85adbce1 884 // The returned multi-dimensional vtable can be fast accessed by the visitor
885 // using index calculation.
f03f26fa 886 template<typename _Array_type, typename _Index_seq>
85adbce1 887 struct __gen_vtable_impl;
888
492debfa 889 // Defines the _S_apply() member that returns a _Multi_array populated
890 // with function pointers that perform the visitation expressions e(m)
891 // for each valid pack of indexes into the variant types _Variants.
892 //
893 // This partial specialization builds up the index sequences by recursively
894 // calling _S_apply() on the next specialization of __gen_vtable_impl.
895 // The base case of the recursion defines the actual function pointers.
f03f26fa 896 template<typename _Result_type, typename _Visitor, size_t... __dimensions,
2a5d61f9 897 typename... _Variants, size_t... __indices>
898 struct __gen_vtable_impl<
a4e92d65 899 _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
f03f26fa 900 std::index_sequence<__indices...>>
85adbce1 901 {
2a5d61f9 902 using _Next =
903 remove_reference_t<typename _Nth_type<sizeof...(__indices),
904 _Variants...>::type>;
905 using _Array_type =
a4e92d65 906 _Multi_array<_Result_type (*)(_Visitor, _Variants...),
907 __dimensions...>;
2a5d61f9 908
85adbce1 909 static constexpr _Array_type
910 _S_apply()
911 {
912 _Array_type __vtable{};
913 _S_apply_all_alts(
2a5d61f9 914 __vtable, make_index_sequence<variant_size_v<_Next>>());
85adbce1 915 return __vtable;
916 }
917
2a5d61f9 918 template<size_t... __var_indices>
85adbce1 919 static constexpr void
2a5d61f9 920 _S_apply_all_alts(_Array_type& __vtable,
921 std::index_sequence<__var_indices...>)
922 {
4c0ef551 923 if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value)
49c83dca 924 (_S_apply_single_alt<true, __var_indices>(
925 __vtable._M_arr[__var_indices + 1],
926 &(__vtable._M_arr[0])), ...);
927 else
928 (_S_apply_single_alt<false, __var_indices>(
929 __vtable._M_arr[__var_indices]), ...);
2a5d61f9 930 }
85adbce1 931
49c83dca 932 template<bool __do_cookie, size_t __index, typename _Tp>
85adbce1 933 static constexpr void
49c83dca 934 _S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr)
85adbce1 935 {
49c83dca 936 if constexpr (__do_cookie)
937 {
938 __element = __gen_vtable_impl<
939 _Tp,
49c83dca 940 std::index_sequence<__indices..., __index>>::_S_apply();
941 *__cookie_element = __gen_vtable_impl<
942 _Tp,
49c83dca 943 std::index_sequence<__indices..., variant_npos>>::_S_apply();
944 }
945 else
946 {
947 __element = __gen_vtable_impl<
f03f26fa 948 remove_reference_t<decltype(__element)>,
49c83dca 949 std::index_sequence<__indices..., __index>>::_S_apply();
950 }
85adbce1 951 }
952 };
953
492debfa 954 // This partial specialization is the base case for the recursion.
955 // It populates a _Multi_array element with the address of a function
956 // that invokes the visitor with the alternatives specified by __indices.
f03f26fa 957 template<typename _Result_type, typename _Visitor, typename... _Variants,
2a5d61f9 958 size_t... __indices>
85adbce1 959 struct __gen_vtable_impl<
2a5d61f9 960 _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
f03f26fa 961 std::index_sequence<__indices...>>
85adbce1 962 {
963 using _Array_type =
492debfa 964 _Multi_array<_Result_type (*)(_Visitor, _Variants...)>;
2a5d61f9 965
49c83dca 966 template<size_t __index, typename _Variant>
967 static constexpr decltype(auto)
e11f5aed 968 __element_by_index_or_cookie(_Variant&& __var) noexcept
49c83dca 969 {
970 if constexpr (__index != variant_npos)
971 return __variant::__get<__index>(std::forward<_Variant>(__var));
972 else
973 return __variant_cookie{};
974 }
975
4429133c 976 static constexpr decltype(auto)
f03f26fa 977 __visit_invoke(_Visitor&& __visitor, _Variants... __vars)
2a5d61f9 978 {
492debfa 979 if constexpr (is_same_v<_Result_type, __variant_idx_cookie>)
f03f26fa 980 // For raw visitation using indices, pass the indices to the visitor
981 // and discard the return value:
982 std::__invoke(std::forward<_Visitor>(__visitor),
492debfa 983 __element_by_index_or_cookie<__indices>(
984 std::forward<_Variants>(__vars))...,
985 integral_constant<size_t, __indices>()...);
f03f26fa 986 else if constexpr (is_same_v<_Result_type, __variant_cookie>)
987 // For raw visitation without indices, and discard the return value:
988 std::__invoke(std::forward<_Visitor>(__visitor),
492debfa 989 __element_by_index_or_cookie<__indices>(
990 std::forward<_Variants>(__vars))...);
f03f26fa 991 else if constexpr (_Array_type::__result_is_deduced::value)
992 // For the usual std::visit case deduce the return value:
4f3e024d 993 return std::__invoke(std::forward<_Visitor>(__visitor),
492debfa 994 __element_by_index_or_cookie<__indices>(
995 std::forward<_Variants>(__vars))...);
f03f26fa 996 else // for std::visit<R> use INVOKE<R>
997 return std::__invoke_r<_Result_type>(
998 std::forward<_Visitor>(__visitor),
999 __variant::__get<__indices>(std::forward<_Variants>(__vars))...);
ff7d433d 1000 }
1001
85adbce1 1002 static constexpr auto
1003 _S_apply()
2a5d61f9 1004 { return _Array_type{&__visit_invoke}; }
85adbce1 1005 };
1006
f03f26fa 1007 template<typename _Result_type, typename _Visitor, typename... _Variants>
85adbce1 1008 struct __gen_vtable
1009 {
85adbce1 1010 using _Array_type =
492debfa 1011 _Multi_array<_Result_type (*)(_Visitor, _Variants...),
28b460dd 1012 variant_size_v<remove_reference_t<_Variants>>...>;
85adbce1 1013
492debfa 1014 static constexpr _Array_type _S_vtable
f03f26fa 1015 = __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply();
85adbce1 1016 };
1017
a6787bda 1018 template<size_t _Np, typename _Tp>
1019 struct _Base_dedup : public _Tp { };
1020
1021 template<typename _Variant, typename __indices>
1022 struct _Variant_hash_base;
1023
1024 template<typename... _Types, size_t... __indices>
1025 struct _Variant_hash_base<variant<_Types...>,
1026 std::index_sequence<__indices...>>
1027 : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
1028
85adbce1 1029} // namespace __variant
1030} // namespace __detail
1031
49c83dca 1032 template<size_t _Np, typename _Variant, typename... _Args>
1033 void __variant_construct_by_index(_Variant& __v, _Args&&... __args)
1034 {
1035 __v._M_index = _Np;
1036 auto&& __storage = __detail::__variant::__get<_Np>(__v);
1037 ::new ((void*)std::addressof(__storage))
1038 remove_reference_t<decltype(__storage)>
1039 (std::forward<_Args>(__args)...);
1040 }
1041
85adbce1 1042 template<typename _Tp, typename... _Types>
4429133c 1043 constexpr bool
1044 holds_alternative(const variant<_Types...>& __v) noexcept
85adbce1 1045 {
1046 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1047 "T should occur for exactly once in alternatives");
1048 return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>;
1049 }
1050
85adbce1 1051 template<typename _Tp, typename... _Types>
4429133c 1052 constexpr _Tp& get(variant<_Types...>& __v)
85adbce1 1053 {
1054 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1055 "T should occur for exactly once in alternatives");
1056 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1057 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
85adbce1 1058 }
1059
1060 template<typename _Tp, typename... _Types>
4429133c 1061 constexpr _Tp&& get(variant<_Types...>&& __v)
85adbce1 1062 {
1063 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1064 "T should occur for exactly once in alternatives");
1065 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1066 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
85adbce1 1067 std::move(__v));
1068 }
1069
1070 template<typename _Tp, typename... _Types>
4429133c 1071 constexpr const _Tp& get(const variant<_Types...>& __v)
85adbce1 1072 {
1073 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1074 "T should occur for exactly once in alternatives");
1075 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1076 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
85adbce1 1077 }
1078
1079 template<typename _Tp, typename... _Types>
4429133c 1080 constexpr const _Tp&& get(const variant<_Types...>&& __v)
85adbce1 1081 {
1082 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1083 "T should occur for exactly once in alternatives");
1084 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1085 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
85adbce1 1086 std::move(__v));
1087 }
1088
1089 template<size_t _Np, typename... _Types>
4429133c 1090 constexpr add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>>
85adbce1 1091 get_if(variant<_Types...>* __ptr) noexcept
1092 {
1093 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
1094 static_assert(_Np < sizeof...(_Types),
1095 "The index should be in [0, number of alternatives)");
1096 static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
1097 if (__ptr && __ptr->index() == _Np)
49c83dca 1098 return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
85adbce1 1099 return nullptr;
1100 }
1101
1102 template<size_t _Np, typename... _Types>
4429133c 1103 constexpr
caaaa8fd 1104 add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>>
85adbce1 1105 get_if(const variant<_Types...>* __ptr) noexcept
1106 {
1107 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
1108 static_assert(_Np < sizeof...(_Types),
1109 "The index should be in [0, number of alternatives)");
1110 static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
1111 if (__ptr && __ptr->index() == _Np)
49c83dca 1112 return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
85adbce1 1113 return nullptr;
1114 }
1115
1116 template<typename _Tp, typename... _Types>
4429133c 1117 constexpr add_pointer_t<_Tp>
caaaa8fd 1118 get_if(variant<_Types...>* __ptr) noexcept
85adbce1 1119 {
1120 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1121 "T should occur for exactly once in alternatives");
1122 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1123 return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
1124 __ptr);
85adbce1 1125 }
1126
1127 template<typename _Tp, typename... _Types>
4429133c 1128 constexpr add_pointer_t<const _Tp>
e11f5aed 1129 get_if(const variant<_Types...>* __ptr) noexcept
85adbce1 1130 {
1131 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1132 "T should occur for exactly once in alternatives");
1133 static_assert(!is_void_v<_Tp>, "_Tp should not be void");
4a12299e 1134 return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
1135 __ptr);
85adbce1 1136 }
1137
824ecf42 1138 struct monostate { };
85adbce1 1139
824ecf42 1140#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
1141 template<typename... _Types> \
1142 constexpr bool operator __OP(const variant<_Types...>& __lhs, \
1143 const variant<_Types...>& __rhs) \
1144 { \
49c83dca 1145 bool __ret = true; \
f03f26fa 1146 __detail::__variant::__raw_idx_visit( \
1147 [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \
49c83dca 1148 { \
4f3e024d 1149 if constexpr (__rhs_index != variant_npos) \
1150 { \
1151 if (__lhs.index() == __rhs_index) \
1152 { \
1153 auto& __this_mem = std::get<__rhs_index>(__lhs); \
1154 __ret = __this_mem __OP __rhs_mem; \
1155 } \
1156 else \
1157 __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
1158 } \
1159 else \
1160 __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
4f3e024d 1161 }, __rhs); \
49c83dca 1162 return __ret; \
824ecf42 1163 } \
1164\
1165 constexpr bool operator __OP(monostate, monostate) noexcept \
1166 { return 0 __OP 0; }
1167
1168 _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
1169 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
1170 _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
1171 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
1172 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
1173 _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
1174
1175#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
85adbce1 1176
1177 template<typename _Visitor, typename... _Variants>
2a5d61f9 1178 constexpr decltype(auto) visit(_Visitor&&, _Variants&&...);
85adbce1 1179
85adbce1 1180 template<typename... _Types>
a6787bda 1181 inline enable_if_t<(is_move_constructible_v<_Types> && ...)
1182 && (is_swappable_v<_Types> && ...)>
f89b61dd 1183 swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
1184 noexcept(noexcept(__lhs.swap(__rhs)))
85adbce1 1185 { __lhs.swap(__rhs); }
1186
f89b61dd 1187 template<typename... _Types>
fd1c8642 1188 enable_if_t<!((is_move_constructible_v<_Types> && ...)
1189 && (is_swappable_v<_Types> && ...))>
f89b61dd 1190 swap(variant<_Types...>&, variant<_Types...>&) = delete;
1191
85adbce1 1192 class bad_variant_access : public exception
1193 {
1194 public:
1195 bad_variant_access() noexcept : _M_reason("Unknown reason") { }
1196 const char* what() const noexcept override
1197 { return _M_reason; }
1198
1199 private:
1200 bad_variant_access(const char* __reason) : _M_reason(__reason) { }
1201
1202 const char* _M_reason;
1203
1204 friend void __throw_bad_variant_access(const char* __what);
1205 };
1206
1207 inline void
1208 __throw_bad_variant_access(const char* __what)
1209 { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
1210
1211 template<typename... _Types>
1212 class variant
1213 : private __detail::__variant::_Variant_base<_Types...>,
1214 private _Enable_default_constructor<
ae6a4ce9 1215 __detail::__variant::_Traits<_Types...>::_S_default_ctor,
77c62063 1216 variant<_Types...>>,
85adbce1 1217 private _Enable_copy_move<
ae6a4ce9 1218 __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
1219 __detail::__variant::_Traits<_Types...>::_S_copy_assign,
1220 __detail::__variant::_Traits<_Types...>::_S_move_ctor,
1221 __detail::__variant::_Traits<_Types...>::_S_move_assign,
85adbce1 1222 variant<_Types...>>
1223 {
1224 private:
49c83dca 1225 template <typename... _UTypes, typename _Tp>
1226 friend decltype(auto) __variant_cast(_Tp&&);
1227 template<size_t _Np, typename _Variant, typename... _Args>
1228 friend void __variant_construct_by_index(_Variant& __v,
1229 _Args&&... __args);
1230
f24f2a9e 1231 static_assert(sizeof...(_Types) > 0,
1232 "variant must have at least one alternative");
1233 static_assert(!(std::is_reference_v<_Types> || ...),
1234 "variant must have no reference alternative");
1235 static_assert(!(std::is_void_v<_Types> || ...),
1236 "variant must have no void alternative");
1237
85adbce1 1238 using _Base = __detail::__variant::_Variant_base<_Types...>;
1239 using _Default_ctor_enabler =
ae6a4ce9 1240 _Enable_default_constructor<
1241 __detail::__variant::_Traits<_Types...>::_S_default_ctor,
1242 variant<_Types...>>;
85adbce1 1243
28cc38ec 1244 template<typename _Tp>
1245 static constexpr bool __not_self
1246 = !is_same_v<__remove_cvref_t<_Tp>, variant>;
1247
85adbce1 1248 template<typename _Tp>
1249 static constexpr bool
1250 __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
1251
1252 template<typename _Tp>
1253 static constexpr size_t __accepted_index =
1254 __detail::__variant::__accepted_index<_Tp&&, variant>::value;
1255
28cc38ec 1256 template<size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>>
1257 using __to_type = variant_alternative_t<_Np, variant>;
85adbce1 1258
28cc38ec 1259 template<typename _Tp, typename = enable_if_t<__not_self<_Tp>>>
85adbce1 1260 using __accepted_type = __to_type<__accepted_index<_Tp>>;
1261
85adbce1 1262 template<typename _Tp>
1263 static constexpr size_t __index_of =
1264 __detail::__variant::__index_of_v<_Tp, _Types...>;
1265
77c62063 1266 using _Traits = __detail::__variant::_Traits<_Types...>;
1267
28cc38ec 1268 template<typename _Tp>
1269 struct __is_in_place_tag : false_type { };
1270 template<typename _Tp>
1271 struct __is_in_place_tag<in_place_type_t<_Tp>> : true_type { };
1272 template<size_t _Np>
1273 struct __is_in_place_tag<in_place_index_t<_Np>> : true_type { };
1274
1275 template<typename _Tp>
1276 static constexpr bool __not_in_place_tag
1277 = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value;
1278
85adbce1 1279 public:
77c62063 1280 variant() = default;
1281 variant(const variant& __rhs) = default;
1282 variant(variant&&) = default;
1283 variant& operator=(const variant&) = default;
1284 variant& operator=(variant&&) = default;
1285 ~variant() = default;
85adbce1 1286
1287 template<typename _Tp,
28cc38ec 1288 typename = enable_if_t<sizeof...(_Types) != 0>,
1289 typename = enable_if_t<__not_in_place_tag<_Tp>>,
1290 typename _Tj = __accepted_type<_Tp&&>,
1291 typename = enable_if_t<__exactly_once<_Tj>
1292 && is_constructible_v<_Tj, _Tp>>>
85adbce1 1293 constexpr
1294 variant(_Tp&& __t)
28cc38ec 1295 noexcept(is_nothrow_constructible_v<_Tj, _Tp>)
77c62063 1296 : variant(in_place_index<__accepted_index<_Tp&&>>,
ae6a4ce9 1297 std::forward<_Tp>(__t))
e1d699b8 1298 { }
85adbce1 1299
1300 template<typename _Tp, typename... _Args,
1301 typename = enable_if_t<__exactly_once<_Tp>
28cc38ec 1302 && is_constructible_v<_Tp, _Args...>>>
85adbce1 1303 constexpr explicit
1304 variant(in_place_type_t<_Tp>, _Args&&... __args)
77c62063 1305 : variant(in_place_index<__index_of<_Tp>>,
ae6a4ce9 1306 std::forward<_Args>(__args)...)
e1d699b8 1307 { }
85adbce1 1308
1309 template<typename _Tp, typename _Up, typename... _Args,
1310 typename = enable_if_t<__exactly_once<_Tp>
28cc38ec 1311 && is_constructible_v<_Tp,
1312 initializer_list<_Up>&, _Args...>>>
85adbce1 1313 constexpr explicit
1314 variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
1315 _Args&&... __args)
ee6c971a 1316 : variant(in_place_index<__index_of<_Tp>>, __il,
4d1e18aa 1317 std::forward<_Args>(__args)...)
e1d699b8 1318 { }
85adbce1 1319
1320 template<size_t _Np, typename... _Args,
28cc38ec 1321 typename _Tp = __to_type<_Np>,
1322 typename = enable_if_t<is_constructible_v<_Tp, _Args...>>>
85adbce1 1323 constexpr explicit
1324 variant(in_place_index_t<_Np>, _Args&&... __args)
ee6c971a 1325 : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
85adbce1 1326 _Default_ctor_enabler(_Enable_default_constructor_tag{})
e1d699b8 1327 { }
85adbce1 1328
1329 template<size_t _Np, typename _Up, typename... _Args,
28cc38ec 1330 typename _Tp = __to_type<_Np>,
1331 typename = enable_if_t<is_constructible_v<_Tp,
1332 initializer_list<_Up>&,
1333 _Args...>>>
85adbce1 1334 constexpr explicit
1335 variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
1336 _Args&&... __args)
ee6c971a 1337 : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
85adbce1 1338 _Default_ctor_enabler(_Enable_default_constructor_tag{})
e1d699b8 1339 { }
85adbce1 1340
85adbce1 1341 template<typename _Tp>
1342 enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
28cc38ec 1343 && is_constructible_v<__accepted_type<_Tp&&>, _Tp>
1344 && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>,
1345 variant&>
85adbce1 1346 operator=(_Tp&& __rhs)
28cc38ec 1347 noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>
1348 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>)
85adbce1 1349 {
1350 constexpr auto __index = __accepted_index<_Tp&&>;
1351 if (index() == __index)
4e820860 1352 std::get<__index>(*this) = std::forward<_Tp>(__rhs);
85adbce1 1353 else
fd1863e1 1354 {
1355 using _Tj = __accepted_type<_Tp&&>;
1356 if constexpr (is_nothrow_constructible_v<_Tj, _Tp>
1357 || !is_nothrow_move_constructible_v<_Tj>)
1358 this->emplace<__index>(std::forward<_Tp>(__rhs));
1359 else
1360 operator=(variant(std::forward<_Tp>(__rhs)));
1361 }
85adbce1 1362 return *this;
1363 }
1364
1365 template<typename _Tp, typename... _Args>
87da0999 1366 enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
1367 _Tp&>
a6787bda 1368 emplace(_Args&&... __args)
85adbce1 1369 {
e1d699b8 1370 constexpr size_t __index = __index_of<_Tp>;
1371 return this->emplace<__index>(std::forward<_Args>(__args)...);
85adbce1 1372 }
1373
1374 template<typename _Tp, typename _Up, typename... _Args>
a6787bda 1375 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
87da0999 1376 && __exactly_once<_Tp>,
1377 _Tp&>
a6787bda 1378 emplace(initializer_list<_Up> __il, _Args&&... __args)
85adbce1 1379 {
e1d699b8 1380 constexpr size_t __index = __index_of<_Tp>;
1381 return this->emplace<__index>(__il, std::forward<_Args>(__args)...);
85adbce1 1382 }
1383
1384 template<size_t _Np, typename... _Args>
a6787bda 1385 enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
87da0999 1386 _Args...>,
1387 variant_alternative_t<_Np, variant>&>
a6787bda 1388 emplace(_Args&&... __args)
85adbce1 1389 {
1390 static_assert(_Np < sizeof...(_Types),
1391 "The index should be in [0, number of alternatives)");
8815ac91 1392 using type = variant_alternative_t<_Np, variant>;
781cb64d 1393 // Provide the strong exception-safety guarantee when possible,
1394 // to avoid becoming valueless.
1395 if constexpr (is_nothrow_constructible_v<type, _Args...>)
1396 {
1397 this->_M_reset();
1398 __variant_construct_by_index<_Np>(*this,
1399 std::forward<_Args>(__args)...);
1400 }
1401 else if constexpr (is_scalar_v<type>)
8815ac91 1402 {
781cb64d 1403 // This might invoke a potentially-throwing conversion operator:
1404 const type __tmp(std::forward<_Args>(__args)...);
1405 // But these steps won't throw:
1406 this->_M_reset();
1407 __variant_construct_by_index<_Np>(*this, __tmp);
1408 }
b9d8292f 1409 else if constexpr (__detail::__variant::_Never_valueless_alt<type>()
1410 && _Traits::_S_move_assign)
781cb64d 1411 {
1412 // This construction might throw:
8815ac91 1413 variant __tmp(in_place_index<_Np>,
1414 std::forward<_Args>(__args)...);
781cb64d 1415 // But _Never_valueless_alt<type> means this won't:
8815ac91 1416 *this = std::move(__tmp);
85adbce1 1417 }
781cb64d 1418 else
85adbce1 1419 {
781cb64d 1420 // This case only provides the basic exception-safety guarantee,
1421 // i.e. the variant can become valueless.
1422 this->_M_reset();
1423 __try
1424 {
1425 __variant_construct_by_index<_Np>(*this,
1426 std::forward<_Args>(__args)...);
1427 }
1428 __catch (...)
1429 {
1430 this->_M_index = variant_npos;
1431 __throw_exception_again;
1432 }
85adbce1 1433 }
87da0999 1434 return std::get<_Np>(*this);
85adbce1 1435 }
1436
1437 template<size_t _Np, typename _Up, typename... _Args>
a6787bda 1438 enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
87da0999 1439 initializer_list<_Up>&, _Args...>,
1440 variant_alternative_t<_Np, variant>&>
a6787bda 1441 emplace(initializer_list<_Up> __il, _Args&&... __args)
85adbce1 1442 {
1443 static_assert(_Np < sizeof...(_Types),
1444 "The index should be in [0, number of alternatives)");
8815ac91 1445 using type = variant_alternative_t<_Np, variant>;
781cb64d 1446 // Provide the strong exception-safety guarantee when possible,
1447 // to avoid becoming valueless.
1448 if constexpr (is_nothrow_constructible_v<type,
1449 initializer_list<_Up>&,
1450 _Args...>)
8815ac91 1451 {
781cb64d 1452 this->_M_reset();
1453 __variant_construct_by_index<_Np>(*this, __il,
1454 std::forward<_Args>(__args)...);
1455 }
b9d8292f 1456 else if constexpr (__detail::__variant::_Never_valueless_alt<type>()
1457 && _Traits::_S_move_assign)
781cb64d 1458 {
1459 // This construction might throw:
8815ac91 1460 variant __tmp(in_place_index<_Np>, __il,
1461 std::forward<_Args>(__args)...);
781cb64d 1462 // But _Never_valueless_alt<type> means this won't:
8815ac91 1463 *this = std::move(__tmp);
85adbce1 1464 }
781cb64d 1465 else
85adbce1 1466 {
781cb64d 1467 // This case only provides the basic exception-safety guarantee,
1468 // i.e. the variant can become valueless.
1469 this->_M_reset();
1470 __try
1471 {
1472 __variant_construct_by_index<_Np>(*this, __il,
1473 std::forward<_Args>(__args)...);
1474 }
1475 __catch (...)
1476 {
1477 this->_M_index = variant_npos;
1478 __throw_exception_again;
1479 }
85adbce1 1480 }
87da0999 1481 return std::get<_Np>(*this);
85adbce1 1482 }
1483
1484 constexpr bool valueless_by_exception() const noexcept
1485 { return !this->_M_valid(); }
1486
1487 constexpr size_t index() const noexcept
cfdb4aba 1488 {
1489 if (this->_M_index ==
77c62063 1490 typename _Base::__index_type(variant_npos))
cfdb4aba 1491 return variant_npos;
1492 return this->_M_index;
1493 }
85adbce1 1494
1495 void
1496 swap(variant& __rhs)
fd1c8642 1497 noexcept((__is_nothrow_swappable<_Types>::value && ...)
a6787bda 1498 && is_nothrow_move_constructible_v<variant>)
85adbce1 1499 {
f03f26fa 1500 __detail::__variant::__raw_idx_visit(
1501 [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable
85adbce1 1502 {
4f3e024d 1503 if constexpr (__rhs_index != variant_npos)
85adbce1 1504 {
4f3e024d 1505 if (this->index() == __rhs_index)
49c83dca 1506 {
4f3e024d 1507 auto& __this_mem =
1508 std::get<__rhs_index>(*this);
49c83dca 1509 using std::swap;
1510 swap(__this_mem, __rhs_mem);
1511 }
4f3e024d 1512 else
1513 {
1514 if (this->index() != variant_npos)
1515 {
1516 auto __tmp(std::move(__rhs_mem));
1517 __rhs = std::move(*this);
1518 this->_M_destructive_move(__rhs_index,
1519 std::move(__tmp));
1520 }
1521 else
1522 {
1523 this->_M_destructive_move(__rhs_index,
1524 std::move(__rhs_mem));
1525 __rhs._M_reset();
1526 }
1527 }
85adbce1 1528 }
49c83dca 1529 else
1530 {
4f3e024d 1531 if (this->index() != variant_npos)
49c83dca 1532 {
4f3e024d 1533 __rhs = std::move(*this);
49c83dca 1534 this->_M_reset();
1535 }
49c83dca 1536 }
4f3e024d 1537 }, __rhs);
85adbce1 1538 }
1539
caaaa8fd 1540 private:
caaaa8fd 1541
a9267d6a 1542#if defined(__clang__) && __clang_major__ <= 7
a8f8d460 1543 public:
1544 using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852
1545 private:
1546#endif
1547
caaaa8fd 1548 template<size_t _Np, typename _Vp>
5c6334a5 1549 friend constexpr decltype(auto)
1550 __detail::__variant::__get(_Vp&& __v) noexcept;
caaaa8fd 1551
85adbce1 1552 template<typename _Vp>
5c6334a5 1553 friend void*
1554 __detail::__variant::__get_storage(_Vp&& __v) noexcept;
caaaa8fd 1555
824ecf42 1556#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
1557 template<typename... _Tp> \
1558 friend constexpr bool \
1559 operator __OP(const variant<_Tp...>& __lhs, \
1560 const variant<_Tp...>& __rhs);
1561
1562 _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
1563 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
1564 _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
1565 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
1566 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
1567 _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
caaaa8fd 1568
824ecf42 1569#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
85adbce1 1570 };
1571
85adbce1 1572 template<size_t _Np, typename... _Types>
caaaa8fd 1573 constexpr variant_alternative_t<_Np, variant<_Types...>>&
85adbce1 1574 get(variant<_Types...>& __v)
1575 {
1576 static_assert(_Np < sizeof...(_Types),
1577 "The index should be in [0, number of alternatives)");
1578 if (__v.index() != _Np)
1579 __throw_bad_variant_access("Unexpected index");
caaaa8fd 1580 return __detail::__variant::__get<_Np>(__v);
85adbce1 1581 }
1582
1583 template<size_t _Np, typename... _Types>
caaaa8fd 1584 constexpr variant_alternative_t<_Np, variant<_Types...>>&&
85adbce1 1585 get(variant<_Types...>&& __v)
1586 {
1587 static_assert(_Np < sizeof...(_Types),
1588 "The index should be in [0, number of alternatives)");
1589 if (__v.index() != _Np)
1590 __throw_bad_variant_access("Unexpected index");
caaaa8fd 1591 return __detail::__variant::__get<_Np>(std::move(__v));
85adbce1 1592 }
1593
1594 template<size_t _Np, typename... _Types>
caaaa8fd 1595 constexpr const variant_alternative_t<_Np, variant<_Types...>>&
85adbce1 1596 get(const variant<_Types...>& __v)
1597 {
1598 static_assert(_Np < sizeof...(_Types),
1599 "The index should be in [0, number of alternatives)");
1600 if (__v.index() != _Np)
1601 __throw_bad_variant_access("Unexpected index");
caaaa8fd 1602 return __detail::__variant::__get<_Np>(__v);
85adbce1 1603 }
1604
1605 template<size_t _Np, typename... _Types>
caaaa8fd 1606 constexpr const variant_alternative_t<_Np, variant<_Types...>>&&
85adbce1 1607 get(const variant<_Types...>&& __v)
1608 {
1609 static_assert(_Np < sizeof...(_Types),
1610 "The index should be in [0, number of alternatives)");
1611 if (__v.index() != _Np)
1612 __throw_bad_variant_access("Unexpected index");
caaaa8fd 1613 return __detail::__variant::__get<_Np>(std::move(__v));
85adbce1 1614 }
1615
f03f26fa 1616 template<typename _Result_type, typename _Visitor, typename... _Variants>
2a5d61f9 1617 constexpr decltype(auto)
49c83dca 1618 __do_visit(_Visitor&& __visitor, _Variants&&... __variants)
85adbce1 1619 {
2a5d61f9 1620 constexpr auto& __vtable = __detail::__variant::__gen_vtable<
1621 _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
1622
1623 auto __func_ptr = __vtable._M_access(__variants.index()...);
4d1e18aa 1624 return (*__func_ptr)(std::forward<_Visitor>(__visitor),
2a5d61f9 1625 std::forward<_Variants>(__variants)...);
85adbce1 1626 }
1627
49c83dca 1628 template<typename _Visitor, typename... _Variants>
1629 constexpr decltype(auto)
1630 visit(_Visitor&& __visitor, _Variants&&... __variants)
1631 {
1632 if ((__variants.valueless_by_exception() || ...))
1633 __throw_bad_variant_access("Unexpected index");
1634
f03f26fa 1635 using _Result_type = std::invoke_result_t<_Visitor,
1636 decltype(std::get<0>(std::declval<_Variants>()))...>;
1637
1638 using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>;
1639
1640 return __do_visit<_Tag>(std::forward<_Visitor>(__visitor),
1641 std::forward<_Variants>(__variants)...);
49c83dca 1642 }
1643
bfbd20f7 1644#if __cplusplus > 201703L
1645 template<typename _Res, typename _Visitor, typename... _Variants>
1646 constexpr _Res
1647 visit(_Visitor&& __visitor, _Variants&&... __variants)
1648 {
1649 if ((__variants.valueless_by_exception() || ...))
1650 __throw_bad_variant_access("Unexpected index");
1651
f03f26fa 1652 return __do_visit<_Res>(std::forward<_Visitor>(__visitor),
1653 std::forward<_Variants>(__variants)...);
bfbd20f7 1654 }
1655#endif
1656
f59d23d2 1657 template<bool, typename... _Types>
1658 struct __variant_hash_call_base_impl
85adbce1 1659 {
85adbce1 1660 size_t
1661 operator()(const variant<_Types...>& __t) const
f9eb8410 1662 noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
85adbce1 1663 {
49c83dca 1664 size_t __ret;
f03f26fa 1665 __detail::__variant::__raw_visit(
1666 [&__t, &__ret](auto&& __t_mem) mutable
85adbce1 1667 {
49c83dca 1668 using _Type = __remove_cvref_t<decltype(__t_mem)>;
1669 if constexpr (!is_same_v<_Type,
1670 __detail::__variant::__variant_cookie>)
1671 __ret = std::hash<size_t>{}(__t.index())
1672 + std::hash<_Type>{}(__t_mem);
1673 else
1674 __ret = std::hash<size_t>{}(__t.index());
49c83dca 1675 }, __t);
1676 return __ret;
85adbce1 1677 }
1678 };
1679
f59d23d2 1680 template<typename... _Types>
1681 struct __variant_hash_call_base_impl<false, _Types...> {};
1682
1683 template<typename... _Types>
1684 using __variant_hash_call_base =
1685 __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>::
1686 __enable_hash_call &&...), _Types...>;
1687
1688 template<typename... _Types>
1689 struct hash<variant<_Types...>>
1690 : private __detail::__variant::_Variant_hash_base<
ae6a4ce9 1691 variant<_Types...>, std::index_sequence_for<_Types...>>,
f59d23d2 1692 public __variant_hash_call_base<_Types...>
1693 {
b644c5b6 1694 using result_type [[__deprecated__]] = size_t;
1695 using argument_type [[__deprecated__]] = variant<_Types...>;
f59d23d2 1696 };
1697
85adbce1 1698 template<>
1699 struct hash<monostate>
1700 {
b644c5b6 1701 using result_type [[__deprecated__]] = size_t;
1702 using argument_type [[__deprecated__]] = monostate;
85adbce1 1703
1704 size_t
1705 operator()(const monostate& __t) const noexcept
1706 {
1707 constexpr size_t __magic_monostate_hash = -7777;
1708 return __magic_monostate_hash;
1709 }
1710 };
1711
b644c5b6 1712 template<typename... _Types>
1713 struct __is_fast_hash<hash<variant<_Types...>>>
1714 : bool_constant<(__is_fast_hash<_Types>::value && ...)>
1715 { };
1716
85adbce1 1717_GLIBCXX_END_NAMESPACE_VERSION
1718} // namespace std
1719
1720#endif // C++17
1721
1722#endif // _GLIBCXX_VARIANT