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