1// <variant> -*- C++ -*- 2 3// Copyright (C) 2016-2017 Free Software Foundation, Inc. 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 34#if __cplusplus >= 201703L 35 36#include <type_traits> 37#include <utility> 38#include <bits/enable_special_members.h> 39#include <bits/functexcept.h> 40#include <bits/move.h> 41#include <bits/functional_hash.h> 42#include <bits/invoke.h> 43#include <ext/aligned_buffer.h> 44#include <bits/parse_numbers.h> 45#include <bits/stl_iterator_base_types.h> 46#include <bits/stl_iterator_base_funcs.h> 47#include <bits/stl_construct.h> 48 49namespace std _GLIBCXX_VISIBILITY(default) 50{ 51namespace __detail 52{ 53namespace __variant 54{ 55_GLIBCXX_BEGIN_NAMESPACE_VERSION 56 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 68_GLIBCXX_END_NAMESPACE_VERSION 69} // namespace __variant 70} // namespace __detail 71 72_GLIBCXX_BEGIN_NAMESPACE_VERSION 73 74#define __cpp_lib_variant 201603 75 76 template<typename... _Types> class tuple; 77 template<typename... _Types> class variant; 78 template <typename> struct hash; 79 80 template<typename _Variant> 81 struct variant_size; 82 83 template<typename _Variant> 84 struct variant_size<const _Variant> : variant_size<_Variant> {}; 85 86 template<typename _Variant> 87 struct variant_size<volatile _Variant> : variant_size<_Variant> {}; 88 89 template<typename _Variant> 90 struct variant_size<const volatile _Variant> : variant_size<_Variant> {}; 91 92 template<typename... _Types> 93 struct variant_size<variant<_Types...>> 94 : std::integral_constant<size_t, sizeof...(_Types)> {}; 95 96 template<typename _Variant> 97 inline constexpr size_t variant_size_v = variant_size<_Variant>::value; 98 99 template<size_t _Np, typename _Variant> 100 struct variant_alternative; 101 102 template<size_t _Np, typename _First, typename... _Rest> 103 struct variant_alternative<_Np, variant<_First, _Rest...>> 104 : variant_alternative<_Np-1, variant<_Rest...>> {}; 105 106 template<typename _First, typename... _Rest> 107 struct variant_alternative<0, variant<_First, _Rest...>> 108 { using type = _First; }; 109 110 template<size_t _Np, typename _Variant> 111 using variant_alternative_t = 112 typename variant_alternative<_Np, _Variant>::type; 113 114 template<size_t _Np, typename _Variant> 115 struct variant_alternative<_Np, const _Variant> 116 { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; }; 117 118 template<size_t _Np, typename _Variant> 119 struct variant_alternative<_Np, volatile _Variant> 120 { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; }; 121 122 template<size_t _Np, typename _Variant> 123 struct variant_alternative<_Np, const volatile _Variant> 124 { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; }; 125 126 inline constexpr size_t variant_npos = -1; 127 128 template<size_t _Np, typename... _Types> 129 constexpr variant_alternative_t<_Np, variant<_Types...>>& 130 get(variant<_Types...>&); 131 132 template<size_t _Np, typename... _Types> 133 constexpr variant_alternative_t<_Np, variant<_Types...>>&& 134 get(variant<_Types...>&&); 135 136 template<size_t _Np, typename... _Types> 137 constexpr variant_alternative_t<_Np, variant<_Types...>> const& 138 get(const variant<_Types...>&); 139 140 template<size_t _Np, typename... _Types> 141 constexpr variant_alternative_t<_Np, variant<_Types...>> const&& 142 get(const variant<_Types...>&&); 143 144_GLIBCXX_END_NAMESPACE_VERSION 145 146namespace __detail 147{ 148namespace __variant 149{ 150_GLIBCXX_BEGIN_NAMESPACE_VERSION 151 // Returns the first apparence of _Tp in _Types. 152 // Returns sizeof...(_Types) if _Tp is not in _Types. 153 template<typename _Tp, typename... _Types> 154 struct __index_of : std::integral_constant<size_t, 0> {}; 155 156 template<typename _Tp, typename... _Types> 157 inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value; 158 159 template<typename _Tp, typename _First, typename... _Rest> 160 struct __index_of<_Tp, _First, _Rest...> : 161 std::integral_constant<size_t, is_same_v<_Tp, _First> 162 ? 0 : __index_of_v<_Tp, _Rest...> + 1> {}; 163 164 // _Uninitialized<T> is guaranteed to be a literal type, even if T is not. 165 // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented 166 // yet. When it's implemented, _Uninitialized<T> can be changed to the alias 167 // to T, therefore equivalent to being removed entirely. 168 // 169 // Another reason we may not want to remove _Uninitialzied<T> may be that, we 170 // want _Uninitialized<T> to be trivially destructible, no matter whether T 171 // is; but we will see. 172 template<typename _Type, bool = std::is_literal_type_v<_Type>> 173 struct _Uninitialized; 174 175 template<typename _Type> 176 struct _Uninitialized<_Type, true> 177 { 178 template<typename... _Args> 179 constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) 180 : _M_storage(std::forward<_Args>(__args)...) 181 { } 182 183 constexpr const _Type& _M_get() const & 184 { return _M_storage; } 185 186 constexpr _Type& _M_get() & 187 { return _M_storage; } 188 189 constexpr const _Type&& _M_get() const && 190 { return std::move(_M_storage); } 191 192 constexpr _Type&& _M_get() && 193 { return std::move(_M_storage); } 194 195 _Type _M_storage; 196 }; 197 198 template<typename _Type> 199 struct _Uninitialized<_Type, false> 200 { 201 template<typename... _Args> 202 constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) 203 { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); } 204 205 const _Type& _M_get() const & 206 { return *_M_storage._M_ptr(); } 207 208 _Type& _M_get() & 209 { return *_M_storage._M_ptr(); } 210 211 const _Type&& _M_get() const && 212 { return std::move(*_M_storage._M_ptr()); } 213 214 _Type&& _M_get() && 215 { return std::move(*_M_storage._M_ptr()); } 216 217 __gnu_cxx::__aligned_membuf<_Type> _M_storage; 218 }; 219 220 template<typename _Ref> 221 _Ref __ref_cast(void* __ptr) 222 { 223 return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr)); 224 } 225 226 template<typename _Union> 227 constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u) 228 { return std::forward<_Union>(__u)._M_first._M_get(); } 229 230 template<size_t _Np, typename _Union> 231 constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u) 232 { 233 return __variant::__get(in_place_index<_Np-1>, 234 std::forward<_Union>(__u)._M_rest); 235 } 236 237 // Returns the typed storage for __v. 238 template<size_t _Np, typename _Variant> 239 constexpr decltype(auto) __get(_Variant&& __v) 240 { 241 return __variant::__get(std::in_place_index<_Np>, 242 std::forward<_Variant>(__v)._M_u); 243 } 244 245 // Various functions as "vtable" entries, where those vtables are used by 246 // polymorphic operations. 247 template<typename _Lhs, typename _Rhs> 248 void 249 __erased_ctor(void* __lhs, void* __rhs) 250 { 251 using _Type = remove_reference_t<_Lhs>; 252 ::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs)); 253 } 254 255 template<typename _Variant, size_t _Np> 256 void 257 __erased_dtor(_Variant&& __v) 258 { std::_Destroy(std::__addressof(__variant::__get<_Np>(__v))); } 259 260 template<typename _Lhs, typename _Rhs> 261 void 262 __erased_assign(void* __lhs, void* __rhs) 263 { 264 __variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs); 265 } 266 267 template<typename _Lhs, typename _Rhs> 268 void 269 __erased_swap(void* __lhs, void* __rhs) 270 { 271 using std::swap; 272 swap(__variant::__ref_cast<_Lhs>(__lhs), 273 __variant::__ref_cast<_Rhs>(__rhs)); 274 } 275 276#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 277 template<typename _Variant, size_t _Np> \ 278 constexpr bool \ 279 __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \ 280 { \ 281 return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \ 282 __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \ 283 } 284 285 _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 286 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 287 _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 288 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 289 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 290 _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 291 292#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 293 294 template<typename _Tp> 295 size_t 296 __erased_hash(void* __t) 297 { 298 return std::hash<remove_cv_t<remove_reference_t<_Tp>>>{}( 299 __variant::__ref_cast<_Tp>(__t)); 300 } 301 302 // Defines members and ctors. 303 template<typename... _Types> 304 union _Variadic_union { }; 305 306 template<typename _First, typename... _Rest> 307 union _Variadic_union<_First, _Rest...> 308 { 309 constexpr _Variadic_union() : _M_rest() { } 310 311 template<typename... _Args> 312 constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args) 313 : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) 314 { } 315 316 template<size_t _Np, typename... _Args> 317 constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) 318 : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) 319 { } 320 321 _Uninitialized<_First> _M_first; 322 _Variadic_union<_Rest...> _M_rest; 323 }; 324 325 // Defines index and the dtor, possibly trivial. 326 template<bool __trivially_destructible, typename... _Types> 327 struct _Variant_storage; 328 329 template <typename... _Types> 330 using __select_index = 331 typename __select_int::_Select_int_base<sizeof...(_Types) + 1, 332 unsigned char, 333 unsigned short>::type::value_type; 334 335 template<typename... _Types> 336 struct _Variant_storage<false, _Types...> 337 { 338 template<size_t... __indices> 339 static constexpr void (*_S_vtable[])(const _Variant_storage&) = 340 { &__erased_dtor<const _Variant_storage&, __indices>... }; 341 342 constexpr _Variant_storage() : _M_index(variant_npos) { } 343 344 template<size_t _Np, typename... _Args> 345 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) 346 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), 347 _M_index(_Np) 348 { } 349 350 template<size_t... __indices> 351 constexpr void _M_reset_impl(std::index_sequence<__indices...>) 352 { 353 if (_M_index != __index_type(variant_npos)) 354 _S_vtable<__indices...>[_M_index](*this); 355 } 356 357 void _M_reset() 358 { 359 _M_reset_impl(std::index_sequence_for<_Types...>{}); 360 _M_index = variant_npos; 361 } 362 363 ~_Variant_storage() 364 { _M_reset(); } 365 366 _Variadic_union<_Types...> _M_u; 367 using __index_type = __select_index<_Types...>; 368 __index_type _M_index; 369 }; 370 371 template<typename... _Types> 372 struct _Variant_storage<true, _Types...> 373 { 374 constexpr _Variant_storage() : _M_index(variant_npos) { } 375 376 template<size_t _Np, typename... _Args> 377 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) 378 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), 379 _M_index(_Np) 380 { } 381 382 void _M_reset() 383 { _M_index = variant_npos; } 384 385 _Variadic_union<_Types...> _M_u; 386 using __index_type = __select_index<_Types...>; 387 __index_type _M_index; 388 }; 389 390 // Helps SFINAE on special member functions. Otherwise it can live in variant 391 // class. 392 template<typename... _Types> 393 struct _Variant_base : 394 _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...), 395 _Types...> 396 { 397 using _Storage = 398 _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...), 399 _Types...>; 400 401 constexpr 402 _Variant_base() 403 noexcept(is_nothrow_default_constructible_v< 404 variant_alternative_t<0, variant<_Types...>>>) 405 : _Variant_base(in_place_index<0>) { } 406 407 _Variant_base(const _Variant_base& __rhs) 408 { 409 if (__rhs._M_valid()) 410 { 411 static constexpr void (*_S_vtable[])(void*, void*) = 412 { &__erased_ctor<_Types&, const _Types&>... }; 413 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage()); 414 this->_M_index = __rhs._M_index; 415 } 416 } 417 418 _Variant_base(_Variant_base&& __rhs) 419 noexcept((is_nothrow_move_constructible_v<_Types> && ...)) 420 { 421 if (__rhs._M_valid()) 422 { 423 static constexpr void (*_S_vtable[])(void*, void*) = 424 { &__erased_ctor<_Types&, _Types&&>... }; 425 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage()); 426 this->_M_index = __rhs._M_index; 427 } 428 } 429 430 template<size_t _Np, typename... _Args> 431 constexpr explicit 432 _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) 433 : _Storage(__i, std::forward<_Args>(__args)...) 434 { } 435 436 _Variant_base& 437 operator=(const _Variant_base& __rhs) 438 { 439 if (this->_M_index == __rhs._M_index) 440 { 441 if (__rhs._M_valid()) 442 { 443 static constexpr void (*_S_vtable[])(void*, void*) = 444 { &__erased_assign<_Types&, const _Types&>... }; 445 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage()); 446 } 447 } 448 else 449 { 450 _Variant_base __tmp(__rhs); 451 this->~_Variant_base(); 452 __try 453 { 454 ::new (this) _Variant_base(std::move(__tmp)); 455 } 456 __catch (...) 457 { 458 this->_M_index = variant_npos; 459 __throw_exception_again; 460 } 461 } 462 __glibcxx_assert(this->_M_index == __rhs._M_index); 463 return *this; 464 } 465 466 void _M_destructive_move(_Variant_base&& __rhs) 467 { 468 this->~_Variant_base(); 469 __try 470 { 471 ::new (this) _Variant_base(std::move(__rhs)); 472 } 473 __catch (...) 474 { 475 this->_M_index = variant_npos; 476 __throw_exception_again; 477 } 478 } 479 480 _Variant_base& 481 operator=(_Variant_base&& __rhs) 482 noexcept((is_nothrow_move_constructible_v<_Types> && ...) 483 && (is_nothrow_move_assignable_v<_Types> && ...)) 484 { 485 if (this->_M_index == __rhs._M_index) 486 { 487 if (__rhs._M_valid()) 488 { 489 static constexpr void (*_S_vtable[])(void*, void*) = 490 { &__erased_assign<_Types&, _Types&&>... }; 491 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage()); 492 } 493 } 494 else 495 { 496 _M_destructive_move(std::move(__rhs)); 497 } 498 return *this; 499 } 500 501 void* 502 _M_storage() const 503 { 504 return const_cast<void*>(static_cast<const void*>( 505 std::addressof(_Storage::_M_u))); 506 } 507 508 constexpr bool 509 _M_valid() const noexcept 510 { 511 return this->_M_index != 512 typename _Storage::__index_type(variant_npos); 513 } 514 }; 515 516 // For how many times does _Tp appear in _Tuple? 517 template<typename _Tp, typename _Tuple> 518 struct __tuple_count; 519 520 template<typename _Tp, typename _Tuple> 521 inline constexpr size_t __tuple_count_v = 522 __tuple_count<_Tp, _Tuple>::value; 523 524 template<typename _Tp, typename... _Types> 525 struct __tuple_count<_Tp, tuple<_Types...>> 526 : integral_constant<size_t, 0> { }; 527 528 template<typename _Tp, typename _First, typename... _Rest> 529 struct __tuple_count<_Tp, tuple<_First, _Rest...>> 530 : integral_constant< 531 size_t, 532 __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; 533 534 // TODO: Reuse this in <tuple> ? 535 template<typename _Tp, typename... _Types> 536 inline constexpr bool __exactly_once = 537 __tuple_count_v<_Tp, tuple<_Types...>> == 1; 538 539 // Takes _Types and create an overloaded _S_fun for each type. 540 // If a type appears more than once in _Types, create only one overload. 541 template<typename... _Types> 542 struct __overload_set 543 { static void _S_fun(); }; 544 545 template<typename _First, typename... _Rest> 546 struct __overload_set<_First, _Rest...> : __overload_set<_Rest...> 547 { 548 using __overload_set<_Rest...>::_S_fun; 549 static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 550 }; 551 552 template<typename... _Rest> 553 struct __overload_set<void, _Rest...> : __overload_set<_Rest...> 554 { 555 using __overload_set<_Rest...>::_S_fun; 556 }; 557 558 // Helper for variant(_Tp&&) and variant::operator=(_Tp&&). 559 // __accepted_index maps the arbitrary _Tp to an alternative type in _Variant. 560 template<typename _Tp, typename _Variant, typename = void> 561 struct __accepted_index 562 { static constexpr size_t value = variant_npos; }; 563 564 template<typename _Tp, typename... _Types> 565 struct __accepted_index< 566 _Tp, variant<_Types...>, 567 decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()), 568 std::declval<void>())> 569 { 570 static constexpr size_t value = sizeof...(_Types) - 1 571 - decltype(__overload_set<_Types...>:: 572 _S_fun(std::declval<_Tp>()))::value; 573 }; 574 575 // Returns the raw storage for __v. 576 template<typename _Variant> 577 void* __get_storage(_Variant&& __v) 578 { return __v._M_storage(); } 579 580 // Used for storing multi-dimensional vtable. 581 template<typename _Tp, size_t... _Dimensions> 582 struct _Multi_array 583 { 584 constexpr const _Tp& 585 _M_access() const 586 { return _M_data; } 587 588 _Tp _M_data; 589 }; 590 591 template<typename _Tp, size_t __first, size_t... __rest> 592 struct _Multi_array<_Tp, __first, __rest...> 593 { 594 template<typename... _Args> 595 constexpr const _Tp& 596 _M_access(size_t __first_index, _Args... __rest_indices) const 597 { return _M_arr[__first_index]._M_access(__rest_indices...); } 598 599 _Multi_array<_Tp, __rest...> _M_arr[__first]; 600 }; 601 602 // Creates a multi-dimensional vtable recursively. 603 // 604 // For example, 605 // visit([](auto, auto){}, 606 // variant<int, char>(), // typedef'ed as V1 607 // variant<float, double, long double>()) // typedef'ed as V2 608 // will trigger instantiations of: 609 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>, 610 // tuple<V1&&, V2&&>, std::index_sequence<>> 611 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>, 612 // tuple<V1&&, V2&&>, std::index_sequence<0>> 613 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 614 // tuple<V1&&, V2&&>, std::index_sequence<0, 0>> 615 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 616 // tuple<V1&&, V2&&>, std::index_sequence<0, 1>> 617 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 618 // tuple<V1&&, V2&&>, std::index_sequence<0, 2>> 619 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>, 620 // tuple<V1&&, V2&&>, std::index_sequence<1>> 621 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 622 // tuple<V1&&, V2&&>, std::index_sequence<1, 0>> 623 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 624 // tuple<V1&&, V2&&>, std::index_sequence<1, 1>> 625 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 626 // tuple<V1&&, V2&&>, std::index_sequence<1, 2>> 627 // The returned multi-dimensional vtable can be fast accessed by the visitor 628 // using index calculation. 629 template<typename _Array_type, typename _Variant_tuple, typename _Index_seq> 630 struct __gen_vtable_impl; 631 632 template<typename _Result_type, typename _Visitor, size_t... __dimensions, 633 typename... _Variants, size_t... __indices> 634 struct __gen_vtable_impl< 635 _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, 636 tuple<_Variants...>, std::index_sequence<__indices...>> 637 { 638 using _Next = 639 remove_reference_t<typename _Nth_type<sizeof...(__indices), 640 _Variants...>::type>; 641 using _Array_type = 642 _Multi_array<_Result_type (*)(_Visitor, _Variants...), 643 __dimensions...>; 644 645 static constexpr _Array_type 646 _S_apply() 647 { 648 _Array_type __vtable{}; 649 _S_apply_all_alts( 650 __vtable, make_index_sequence<variant_size_v<_Next>>()); 651 return __vtable; 652 } 653 654 template<size_t... __var_indices> 655 static constexpr void 656 _S_apply_all_alts(_Array_type& __vtable, 657 std::index_sequence<__var_indices...>) 658 { 659 (_S_apply_single_alt<__var_indices>( 660 __vtable._M_arr[__var_indices]), ...); 661 } 662 663 template<size_t __index, typename _Tp> 664 static constexpr void 665 _S_apply_single_alt(_Tp& __element) 666 { 667 using _Alternative = variant_alternative_t<__index, _Next>; 668 __element = __gen_vtable_impl< 669 remove_reference_t< 670 decltype(__element)>, tuple<_Variants...>, 671 std::index_sequence<__indices..., __index>>::_S_apply(); 672 } 673 }; 674 675 template<typename _Result_type, typename _Visitor, typename... _Variants, 676 size_t... __indices> 677 struct __gen_vtable_impl< 678 _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, 679 tuple<_Variants...>, std::index_sequence<__indices...>> 680 { 681 using _Array_type = 682 _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>; 683 684 decltype(auto) 685 static constexpr __visit_invoke(_Visitor&& __visitor, _Variants... __vars) 686 { 687 return std::__invoke(std::forward<_Visitor>(__visitor), 688 std::get<__indices>(std::forward<_Variants>(__vars))...); 689 } 690 691 static constexpr auto 692 _S_apply() 693 { return _Array_type{&__visit_invoke}; } 694 }; 695 696 template<typename _Result_type, typename _Visitor, typename... _Variants> 697 struct __gen_vtable 698 { 699 using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...); 700 using _Array_type = 701 _Multi_array<_Func_ptr, 702 variant_size_v<remove_reference_t<_Variants>>...>; 703 704 static constexpr _Array_type 705 _S_apply() 706 { 707 return __gen_vtable_impl<_Array_type, tuple<_Variants...>, 708 std::index_sequence<>>::_S_apply(); 709 } 710 711 static constexpr auto _S_vtable = _S_apply(); 712 }; 713 714 template<size_t _Np, typename _Tp> 715 struct _Base_dedup : public _Tp { }; 716 717 template<typename _Variant, typename __indices> 718 struct _Variant_hash_base; 719 720 template<typename... _Types, size_t... __indices> 721 struct _Variant_hash_base<variant<_Types...>, 722 std::index_sequence<__indices...>> 723 : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { }; 724 725_GLIBCXX_END_NAMESPACE_VERSION 726} // namespace __variant 727} // namespace __detail 728 729_GLIBCXX_BEGIN_NAMESPACE_VERSION 730 731 template<typename _Tp, typename... _Types> 732 inline constexpr bool holds_alternative(const variant<_Types...>& __v) 733 noexcept 734 { 735 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 736 "T should occur for exactly once in alternatives"); 737 return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>; 738 } 739 740 template<typename _Tp, typename... _Types> 741 constexpr inline _Tp& get(variant<_Types...>& __v) 742 { 743 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 744 "T should occur for exactly once in alternatives"); 745 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 746 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); 747 } 748 749 template<typename _Tp, typename... _Types> 750 constexpr inline _Tp&& get(variant<_Types...>&& __v) 751 { 752 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 753 "T should occur for exactly once in alternatives"); 754 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 755 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( 756 std::move(__v)); 757 } 758 759 template<typename _Tp, typename... _Types> 760 constexpr inline const _Tp& get(const variant<_Types...>& __v) 761 { 762 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 763 "T should occur for exactly once in alternatives"); 764 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 765 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); 766 } 767 768 template<typename _Tp, typename... _Types> 769 constexpr inline const _Tp&& get(const variant<_Types...>&& __v) 770 { 771 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 772 "T should occur for exactly once in alternatives"); 773 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 774 return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( 775 std::move(__v)); 776 } 777 778 template<size_t _Np, typename... _Types> 779 constexpr inline 780 add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>> 781 get_if(variant<_Types...>* __ptr) noexcept 782 { 783 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; 784 static_assert(_Np < sizeof...(_Types), 785 "The index should be in [0, number of alternatives)"); 786 static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void"); 787 if (__ptr && __ptr->index() == _Np) 788 return &__detail::__variant::__get<_Np>(*__ptr); 789 return nullptr; 790 } 791 792 template<size_t _Np, typename... _Types> 793 constexpr inline 794 add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>> 795 get_if(const variant<_Types...>* __ptr) noexcept 796 { 797 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; 798 static_assert(_Np < sizeof...(_Types), 799 "The index should be in [0, number of alternatives)"); 800 static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void"); 801 if (__ptr && __ptr->index() == _Np) 802 return &__detail::__variant::__get<_Np>(*__ptr); 803 return nullptr; 804 } 805 806 template<typename _Tp, typename... _Types> 807 constexpr inline add_pointer_t<_Tp> 808 get_if(variant<_Types...>* __ptr) noexcept 809 { 810 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 811 "T should occur for exactly once in alternatives"); 812 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 813 return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( 814 __ptr); 815 } 816 817 template<typename _Tp, typename... _Types> 818 constexpr inline add_pointer_t<const _Tp> 819 get_if(const variant<_Types...>* __ptr) 820 noexcept 821 { 822 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 823 "T should occur for exactly once in alternatives"); 824 static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 825 return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( 826 __ptr); 827 } 828 829 struct monostate { }; 830 831#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 832 template<typename... _Types> \ 833 constexpr bool operator __OP(const variant<_Types...>& __lhs, \ 834 const variant<_Types...>& __rhs) \ 835 { \ 836 return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \ 837 } \ 838\ 839 constexpr bool operator __OP(monostate, monostate) noexcept \ 840 { return 0 __OP 0; } 841 842 _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 843 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 844 _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 845 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 846 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 847 _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 848 849#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 850 851 template<typename _Visitor, typename... _Variants> 852 constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); 853 854 template<typename... _Types> 855 inline enable_if_t<(is_move_constructible_v<_Types> && ...) 856 && (is_swappable_v<_Types> && ...)> 857 swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) 858 noexcept(noexcept(__lhs.swap(__rhs))) 859 { __lhs.swap(__rhs); } 860 861 template<typename... _Types> 862 enable_if_t<!((is_move_constructible_v<_Types> && ...) 863 && (is_swappable_v<_Types> && ...))> 864 swap(variant<_Types...>&, variant<_Types...>&) = delete; 865 866 class bad_variant_access : public exception 867 { 868 public: 869 bad_variant_access() noexcept : _M_reason("Unknown reason") { } 870 const char* what() const noexcept override 871 { return _M_reason; } 872 873 private: 874 bad_variant_access(const char* __reason) : _M_reason(__reason) { } 875 876 const char* _M_reason; 877 878 friend void __throw_bad_variant_access(const char* __what); 879 }; 880 881 inline void 882 __throw_bad_variant_access(const char* __what) 883 { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); } 884 885 template<typename... _Types> 886 class variant 887 : private __detail::__variant::_Variant_base<_Types...>, 888 private _Enable_default_constructor< 889 is_default_constructible_v< 890 variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>, 891 private _Enable_copy_move< 892 (is_copy_constructible_v<_Types> && ...), 893 (is_copy_constructible_v<_Types> && ...) 894 && (is_move_constructible_v<_Types> && ...) 895 && (is_copy_assignable_v<_Types> && ...), 896 (is_move_constructible_v<_Types> && ...), 897 (is_move_constructible_v<_Types> && ...) 898 && (is_move_assignable_v<_Types> && ...), 899 variant<_Types...>> 900 { 901 private: 902 static_assert(sizeof...(_Types) > 0, 903 "variant must have at least one alternative"); 904 static_assert(!(std::is_reference_v<_Types> || ...), 905 "variant must have no reference alternative"); 906 static_assert(!(std::is_void_v<_Types> || ...), 907 "variant must have no void alternative"); 908 909 using _Base = __detail::__variant::_Variant_base<_Types...>; 910 using _Default_ctor_enabler = 911 _Enable_default_constructor< 912 is_default_constructible_v< 913 variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>; 914 915 template<typename _Tp> 916 static constexpr bool 917 __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; 918 919 template<typename _Tp> 920 static constexpr size_t __accepted_index = 921 __detail::__variant::__accepted_index<_Tp&&, variant>::value; 922 923 template<size_t _Np, bool = _Np < sizeof...(_Types)> 924 struct __to_type_impl; 925 926 template<size_t _Np> 927 struct __to_type_impl<_Np, true> 928 { using type = variant_alternative_t<_Np, variant>; }; 929 930 template<size_t _Np> 931 using __to_type = typename __to_type_impl<_Np>::type; 932 933 template<typename _Tp> 934 using __accepted_type = __to_type<__accepted_index<_Tp>>; 935 936 template<typename _Tp> 937 static constexpr size_t __index_of = 938 __detail::__variant::__index_of_v<_Tp, _Types...>; 939 940 public: 941 constexpr variant() 942 noexcept(is_nothrow_default_constructible_v<__to_type<0>>) = default; 943 variant(const variant&) = default; 944 variant(variant&&) 945 noexcept((is_nothrow_move_constructible_v<_Types> && ...)) = default; 946 947 template<typename _Tp, 948 typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>, 949 typename = enable_if_t<(sizeof...(_Types)>0)>, 950 typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>> 951 && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>> 952 constexpr 953 variant(_Tp&& __t) 954 noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>) 955 : variant(in_place_index<__accepted_index<_Tp&&>>, std::forward<_Tp>(__t)) 956 { __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); } 957 958 template<typename _Tp, typename... _Args, 959 typename = enable_if_t<__exactly_once<_Tp> 960 && is_constructible_v<_Tp, _Args&&...>>> 961 constexpr explicit 962 variant(in_place_type_t<_Tp>, _Args&&... __args) 963 : variant(in_place_index<__index_of<_Tp>>, std::forward<_Args>(__args)...) 964 { __glibcxx_assert(holds_alternative<_Tp>(*this)); } 965 966 template<typename _Tp, typename _Up, typename... _Args, 967 typename = enable_if_t<__exactly_once<_Tp> 968 && is_constructible_v< 969 _Tp, initializer_list<_Up>&, _Args&&...>>> 970 constexpr explicit 971 variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, 972 _Args&&... __args) 973 : variant(in_place_index<__index_of<_Tp>>, __il, 974 std::forward<_Args>(__args)...) 975 { __glibcxx_assert(holds_alternative<_Tp>(*this)); } 976 977 template<size_t _Np, typename... _Args, 978 typename = enable_if_t< 979 is_constructible_v<__to_type<_Np>, _Args&&...>>> 980 constexpr explicit 981 variant(in_place_index_t<_Np>, _Args&&... __args) 982 : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...), 983 _Default_ctor_enabler(_Enable_default_constructor_tag{}) 984 { __glibcxx_assert(index() == _Np); } 985 986 template<size_t _Np, typename _Up, typename... _Args, 987 typename = enable_if_t<is_constructible_v<__to_type<_Np>, 988 initializer_list<_Up>&, _Args&&...>>> 989 constexpr explicit 990 variant(in_place_index_t<_Np>, initializer_list<_Up> __il, 991 _Args&&... __args) 992 : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...), 993 _Default_ctor_enabler(_Enable_default_constructor_tag{}) 994 { __glibcxx_assert(index() == _Np); } 995 996 ~variant() = default; 997 998 variant& operator=(const variant&) = default; 999 variant& operator=(variant&&) 1000 noexcept((is_nothrow_move_constructible_v<_Types> && ...) 1001 && (is_nothrow_move_assignable_v<_Types> && ...)) = default; 1002 1003 template<typename _Tp> 1004 enable_if_t<__exactly_once<__accepted_type<_Tp&&>> 1005 && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&> 1006 && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&> 1007 && !is_same_v<decay_t<_Tp>, variant>, variant&> 1008 operator=(_Tp&& __rhs) 1009 noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&> 1010 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>) 1011 { 1012 constexpr auto __index = __accepted_index<_Tp&&>; 1013 if (index() == __index) 1014 std::get<__index>(*this) = std::forward<_Tp>(__rhs); 1015 else 1016 this->emplace<__index>(std::forward<_Tp>(__rhs)); 1017 __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); 1018 return *this; 1019 } 1020 1021 template<typename _Tp, typename... _Args> 1022 enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>, 1023 _Tp&> 1024 emplace(_Args&&... __args) 1025 { 1026 auto& ret = 1027 this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...); 1028 __glibcxx_assert(holds_alternative<_Tp>(*this)); 1029 return ret; 1030 } 1031 1032 template<typename _Tp, typename _Up, typename... _Args> 1033 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> 1034 && __exactly_once<_Tp>, 1035 _Tp&> 1036 emplace(initializer_list<_Up> __il, _Args&&... __args) 1037 { 1038 auto& ret = 1039 this->emplace<__index_of<_Tp>>(__il, 1040 std::forward<_Args>(__args)...); 1041 __glibcxx_assert(holds_alternative<_Tp>(*this)); 1042 return ret; 1043 } 1044 1045 template<size_t _Np, typename... _Args> 1046 enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>, 1047 _Args...>, 1048 variant_alternative_t<_Np, variant>&> 1049 emplace(_Args&&... __args) 1050 { 1051 static_assert(_Np < sizeof...(_Types), 1052 "The index should be in [0, number of alternatives)"); 1053 this->~variant(); 1054 __try 1055 { 1056 ::new (this) variant(in_place_index<_Np>, 1057 std::forward<_Args>(__args)...); 1058 } 1059 __catch (...) 1060 { 1061 this->_M_index = variant_npos; 1062 __throw_exception_again; 1063 } 1064 __glibcxx_assert(index() == _Np); 1065 return std::get<_Np>(*this); 1066 } 1067 1068 template<size_t _Np, typename _Up, typename... _Args> 1069 enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>, 1070 initializer_list<_Up>&, _Args...>, 1071 variant_alternative_t<_Np, variant>&> 1072 emplace(initializer_list<_Up> __il, _Args&&... __args) 1073 { 1074 static_assert(_Np < sizeof...(_Types), 1075 "The index should be in [0, number of alternatives)"); 1076 this->~variant(); 1077 __try 1078 { 1079 ::new (this) variant(in_place_index<_Np>, __il, 1080 std::forward<_Args>(__args)...); 1081 } 1082 __catch (...) 1083 { 1084 this->_M_index = variant_npos; 1085 __throw_exception_again; 1086 } 1087 __glibcxx_assert(index() == _Np); 1088 return std::get<_Np>(*this); 1089 } 1090 1091 constexpr bool valueless_by_exception() const noexcept 1092 { return !this->_M_valid(); } 1093 1094 constexpr size_t index() const noexcept 1095 { 1096 if (this->_M_index == 1097 typename _Base::_Storage::__index_type(variant_npos)) 1098 return variant_npos; 1099 return this->_M_index; 1100 } 1101 1102 void 1103 swap(variant& __rhs) 1104 noexcept((__is_nothrow_swappable<_Types>::value && ...) 1105 && is_nothrow_move_constructible_v<variant>) 1106 { 1107 if (this->index() == __rhs.index()) 1108 { 1109 if (this->_M_valid()) 1110 { 1111 static constexpr void (*_S_vtable[])(void*, void*) = 1112 { &__detail::__variant::__erased_swap<_Types&, _Types&>... }; 1113 _S_vtable[__rhs._M_index](this->_M_storage(), 1114 __rhs._M_storage()); 1115 } 1116 } 1117 else if (!this->_M_valid()) 1118 { 1119 this->_M_destructive_move(std::move(__rhs)); 1120 __rhs._M_reset(); 1121 } 1122 else if (!__rhs._M_valid()) 1123 { 1124 __rhs._M_destructive_move(std::move(*this)); 1125 this->_M_reset(); 1126 } 1127 else 1128 { 1129 auto __tmp = std::move(__rhs); 1130 __rhs._M_destructive_move(std::move(*this)); 1131 this->_M_destructive_move(std::move(__tmp)); 1132 } 1133 } 1134 1135 private: 1136#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 1137 template<size_t... __indices> \ 1138 static constexpr bool \ 1139 (*_S_erased_##__NAME[])(const variant&, const variant&) = \ 1140 { &__detail::__variant::__erased_##__NAME< \ 1141 const variant&, __indices>... }; \ 1142 template<size_t... __indices> \ 1143 constexpr inline bool \ 1144 _M_##__NAME(const variant& __rhs, \ 1145 std::index_sequence<__indices...>) const \ 1146 { \ 1147 auto __lhs_index = this->index(); \ 1148 auto __rhs_index = __rhs.index(); \ 1149 if (__lhs_index != __rhs_index || valueless_by_exception()) \ 1150 /* Modulo addition. */ \ 1151 return __lhs_index + 1 __OP __rhs_index + 1; \ 1152 return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \ 1153 } 1154 1155 _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 1156 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 1157 _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 1158 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 1159 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 1160 _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 1161 1162#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 1163 1164#ifdef __clang__ 1165 public: 1166 using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 1167 private: 1168#endif 1169 1170 template<size_t _Np, typename _Vp> 1171 friend constexpr decltype(auto) __detail::__variant:: 1172#if _GLIBCXX_INLINE_VERSION 1173 __7:: // Required due to PR c++/59256 1174#endif 1175 __get(_Vp&& __v); 1176 1177 template<typename _Vp> 1178 friend void* __detail::__variant:: 1179#if _GLIBCXX_INLINE_VERSION 1180 __7:: // Required due to PR c++/59256 1181#endif 1182 __get_storage(_Vp&& __v); 1183 1184#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ 1185 template<typename... _Tp> \ 1186 friend constexpr bool \ 1187 operator __OP(const variant<_Tp...>& __lhs, \ 1188 const variant<_Tp...>& __rhs); 1189 1190 _VARIANT_RELATION_FUNCTION_TEMPLATE(<) 1191 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) 1192 _VARIANT_RELATION_FUNCTION_TEMPLATE(==) 1193 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) 1194 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) 1195 _VARIANT_RELATION_FUNCTION_TEMPLATE(>) 1196 1197#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 1198 }; 1199 1200 template<size_t _Np, typename... _Types> 1201 constexpr variant_alternative_t<_Np, variant<_Types...>>& 1202 get(variant<_Types...>& __v) 1203 { 1204 static_assert(_Np < sizeof...(_Types), 1205 "The index should be in [0, number of alternatives)"); 1206 if (__v.index() != _Np) 1207 __throw_bad_variant_access("Unexpected index"); 1208 return __detail::__variant::__get<_Np>(__v); 1209 } 1210 1211 template<size_t _Np, typename... _Types> 1212 constexpr variant_alternative_t<_Np, variant<_Types...>>&& 1213 get(variant<_Types...>&& __v) 1214 { 1215 static_assert(_Np < sizeof...(_Types), 1216 "The index should be in [0, number of alternatives)"); 1217 if (__v.index() != _Np) 1218 __throw_bad_variant_access("Unexpected index"); 1219 return __detail::__variant::__get<_Np>(std::move(__v)); 1220 } 1221 1222 template<size_t _Np, typename... _Types> 1223 constexpr const variant_alternative_t<_Np, variant<_Types...>>& 1224 get(const variant<_Types...>& __v) 1225 { 1226 static_assert(_Np < sizeof...(_Types), 1227 "The index should be in [0, number of alternatives)"); 1228 if (__v.index() != _Np) 1229 __throw_bad_variant_access("Unexpected index"); 1230 return __detail::__variant::__get<_Np>(__v); 1231 } 1232 1233 template<size_t _Np, typename... _Types> 1234 constexpr const variant_alternative_t<_Np, variant<_Types...>>&& 1235 get(const variant<_Types...>&& __v) 1236 { 1237 static_assert(_Np < sizeof...(_Types), 1238 "The index should be in [0, number of alternatives)"); 1239 if (__v.index() != _Np) 1240 __throw_bad_variant_access("Unexpected index"); 1241 return __detail::__variant::__get<_Np>(std::move(__v)); 1242 } 1243 1244 template<typename _Visitor, typename... _Variants> 1245 constexpr decltype(auto) 1246 visit(_Visitor&& __visitor, _Variants&&... __variants) 1247 { 1248 if ((__variants.valueless_by_exception() || ...)) 1249 __throw_bad_variant_access("Unexpected index"); 1250 1251 using _Result_type = 1252 decltype(std::forward<_Visitor>(__visitor)( 1253 std::get<0>(std::forward<_Variants>(__variants))...)); 1254 1255 constexpr auto& __vtable = __detail::__variant::__gen_vtable< 1256 _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; 1257 1258 auto __func_ptr = __vtable._M_access(__variants.index()...); 1259 return (*__func_ptr)(std::forward<_Visitor>(__visitor), 1260 std::forward<_Variants>(__variants)...); 1261 } 1262 1263 template<bool, typename... _Types> 1264 struct __variant_hash_call_base_impl 1265 { 1266 size_t 1267 operator()(const variant<_Types...>& __t) const 1268 noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...)) 1269 { 1270 if (!__t.valueless_by_exception()) 1271 { 1272 namespace __edv = __detail::__variant; 1273 static constexpr size_t (*_S_vtable[])(void*) = 1274 { &__edv::__erased_hash<const _Types&>... }; 1275 return hash<size_t>{}(__t.index()) 1276 + _S_vtable[__t.index()](__edv::__get_storage(__t)); 1277 } 1278 return hash<size_t>{}(__t.index()); 1279 } 1280 }; 1281 1282 template<typename... _Types> 1283 struct __variant_hash_call_base_impl<false, _Types...> {}; 1284 1285 template<typename... _Types> 1286 using __variant_hash_call_base = 1287 __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>:: 1288 __enable_hash_call &&...), _Types...>; 1289 1290 template<typename... _Types> 1291 struct hash<variant<_Types...>> 1292 : private __detail::__variant::_Variant_hash_base< 1293 variant<_Types...>, std::index_sequence_for<_Types...>>, 1294 public __variant_hash_call_base<_Types...> 1295 { 1296 using result_type = size_t; 1297 using argument_type = variant<_Types...>; 1298 }; 1299 1300 template<> 1301 struct hash<monostate> 1302 { 1303 using result_type = size_t; 1304 using argument_type = monostate; 1305 1306 size_t 1307 operator()(const monostate& __t) const noexcept 1308 { 1309 constexpr size_t __magic_monostate_hash = -7777; 1310 return __magic_monostate_hash; 1311 } 1312 }; 1313 1314_GLIBCXX_END_NAMESPACE_VERSION 1315} // namespace std 1316 1317#endif // C++17 1318 1319#endif // _GLIBCXX_VARIANT 1320