138fd1498Szrj// <variant> -*- C++ -*- 238fd1498Szrj 338fd1498Szrj// Copyright (C) 2016-2018 Free Software Foundation, Inc. 438fd1498Szrj// 538fd1498Szrj// This file is part of the GNU ISO C++ Library. This library is free 638fd1498Szrj// software; you can redistribute it and/or modify it under the 738fd1498Szrj// terms of the GNU General Public License as published by the 838fd1498Szrj// Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj// any later version. 1038fd1498Szrj 1138fd1498Szrj// This library is distributed in the hope that it will be useful, 1238fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj// GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional 1738fd1498Szrj// permissions described in the GCC Runtime Library Exception, version 1838fd1498Szrj// 3.1, as published by the Free Software Foundation. 1938fd1498Szrj 2038fd1498Szrj// You should have received a copy of the GNU General Public License and 2138fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program; 2238fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2338fd1498Szrj// <http://www.gnu.org/licenses/>. 2438fd1498Szrj 2538fd1498Szrj/** @file variant 2638fd1498Szrj * This is the <variant> C++ Library header. 2738fd1498Szrj */ 2838fd1498Szrj 2938fd1498Szrj#ifndef _GLIBCXX_VARIANT 3038fd1498Szrj#define _GLIBCXX_VARIANT 1 3138fd1498Szrj 3238fd1498Szrj#pragma GCC system_header 3338fd1498Szrj 3438fd1498Szrj#if __cplusplus >= 201703L 3538fd1498Szrj 3638fd1498Szrj#include <type_traits> 3738fd1498Szrj#include <utility> 3838fd1498Szrj#include <bits/enable_special_members.h> 3938fd1498Szrj#include <bits/functexcept.h> 4038fd1498Szrj#include <bits/move.h> 4138fd1498Szrj#include <bits/functional_hash.h> 4238fd1498Szrj#include <bits/invoke.h> 4338fd1498Szrj#include <ext/aligned_buffer.h> 4438fd1498Szrj#include <bits/parse_numbers.h> 4538fd1498Szrj#include <bits/stl_iterator_base_types.h> 4638fd1498Szrj#include <bits/stl_iterator_base_funcs.h> 4738fd1498Szrj#include <bits/stl_construct.h> 4838fd1498Szrj 4938fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default) 5038fd1498Szrj{ 5138fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION 5238fd1498Szrj 5338fd1498Szrjnamespace __detail 5438fd1498Szrj{ 5538fd1498Szrjnamespace __variant 5638fd1498Szrj{ 5738fd1498Szrj template<size_t _Np, typename... _Types> 5838fd1498Szrj struct _Nth_type; 5938fd1498Szrj 6038fd1498Szrj template<size_t _Np, typename _First, typename... _Rest> 6138fd1498Szrj struct _Nth_type<_Np, _First, _Rest...> 6238fd1498Szrj : _Nth_type<_Np-1, _Rest...> { }; 6338fd1498Szrj 6438fd1498Szrj template<typename _First, typename... _Rest> 6538fd1498Szrj struct _Nth_type<0, _First, _Rest...> 6638fd1498Szrj { using type = _First; }; 6738fd1498Szrj 6838fd1498Szrj} // namespace __variant 6938fd1498Szrj} // namespace __detail 7038fd1498Szrj 7138fd1498Szrj#define __cpp_lib_variant 201603 7238fd1498Szrj 7338fd1498Szrj template<typename... _Types> class tuple; 7438fd1498Szrj template<typename... _Types> class variant; 7538fd1498Szrj template <typename> struct hash; 7638fd1498Szrj 7738fd1498Szrj template<typename _Variant> 7838fd1498Szrj struct variant_size; 7938fd1498Szrj 8038fd1498Szrj template<typename _Variant> 8138fd1498Szrj struct variant_size<const _Variant> : variant_size<_Variant> {}; 8238fd1498Szrj 8338fd1498Szrj template<typename _Variant> 8438fd1498Szrj struct variant_size<volatile _Variant> : variant_size<_Variant> {}; 8538fd1498Szrj 8638fd1498Szrj template<typename _Variant> 8738fd1498Szrj struct variant_size<const volatile _Variant> : variant_size<_Variant> {}; 8838fd1498Szrj 8938fd1498Szrj template<typename... _Types> 9038fd1498Szrj struct variant_size<variant<_Types...>> 9138fd1498Szrj : std::integral_constant<size_t, sizeof...(_Types)> {}; 9238fd1498Szrj 9338fd1498Szrj template<typename _Variant> 9438fd1498Szrj inline constexpr size_t variant_size_v = variant_size<_Variant>::value; 9538fd1498Szrj 9638fd1498Szrj template<size_t _Np, typename _Variant> 9738fd1498Szrj struct variant_alternative; 9838fd1498Szrj 9938fd1498Szrj template<size_t _Np, typename _First, typename... _Rest> 10038fd1498Szrj struct variant_alternative<_Np, variant<_First, _Rest...>> 10138fd1498Szrj : variant_alternative<_Np-1, variant<_Rest...>> {}; 10238fd1498Szrj 10338fd1498Szrj template<typename _First, typename... _Rest> 10438fd1498Szrj struct variant_alternative<0, variant<_First, _Rest...>> 10538fd1498Szrj { using type = _First; }; 10638fd1498Szrj 10738fd1498Szrj template<size_t _Np, typename _Variant> 10838fd1498Szrj using variant_alternative_t = 10938fd1498Szrj typename variant_alternative<_Np, _Variant>::type; 11038fd1498Szrj 11138fd1498Szrj template<size_t _Np, typename _Variant> 11238fd1498Szrj struct variant_alternative<_Np, const _Variant> 11338fd1498Szrj { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; }; 11438fd1498Szrj 11538fd1498Szrj template<size_t _Np, typename _Variant> 11638fd1498Szrj struct variant_alternative<_Np, volatile _Variant> 11738fd1498Szrj { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; }; 11838fd1498Szrj 11938fd1498Szrj template<size_t _Np, typename _Variant> 12038fd1498Szrj struct variant_alternative<_Np, const volatile _Variant> 12138fd1498Szrj { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; }; 12238fd1498Szrj 12338fd1498Szrj inline constexpr size_t variant_npos = -1; 12438fd1498Szrj 12538fd1498Szrj template<size_t _Np, typename... _Types> 12638fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>>& 12738fd1498Szrj get(variant<_Types...>&); 12838fd1498Szrj 12938fd1498Szrj template<size_t _Np, typename... _Types> 13038fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>>&& 13138fd1498Szrj get(variant<_Types...>&&); 13238fd1498Szrj 13338fd1498Szrj template<size_t _Np, typename... _Types> 13438fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>> const& 13538fd1498Szrj get(const variant<_Types...>&); 13638fd1498Szrj 13738fd1498Szrj template<size_t _Np, typename... _Types> 13838fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>> const&& 13938fd1498Szrj get(const variant<_Types...>&&); 14038fd1498Szrj 14138fd1498Szrjnamespace __detail 14238fd1498Szrj{ 14338fd1498Szrjnamespace __variant 14438fd1498Szrj{ 14538fd1498Szrj // Returns the first apparence of _Tp in _Types. 14638fd1498Szrj // Returns sizeof...(_Types) if _Tp is not in _Types. 14738fd1498Szrj template<typename _Tp, typename... _Types> 14838fd1498Szrj struct __index_of : std::integral_constant<size_t, 0> {}; 14938fd1498Szrj 15038fd1498Szrj template<typename _Tp, typename... _Types> 15138fd1498Szrj inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value; 15238fd1498Szrj 15338fd1498Szrj template<typename _Tp, typename _First, typename... _Rest> 15438fd1498Szrj struct __index_of<_Tp, _First, _Rest...> : 15538fd1498Szrj std::integral_constant<size_t, is_same_v<_Tp, _First> 15638fd1498Szrj ? 0 : __index_of_v<_Tp, _Rest...> + 1> {}; 15738fd1498Szrj 15838fd1498Szrj // _Uninitialized<T> is guaranteed to be a literal type, even if T is not. 15938fd1498Szrj // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented 16038fd1498Szrj // yet. When it's implemented, _Uninitialized<T> can be changed to the alias 16138fd1498Szrj // to T, therefore equivalent to being removed entirely. 16238fd1498Szrj // 16338fd1498Szrj // Another reason we may not want to remove _Uninitialzied<T> may be that, we 16438fd1498Szrj // want _Uninitialized<T> to be trivially destructible, no matter whether T 16538fd1498Szrj // is; but we will see. 16638fd1498Szrj template<typename _Type, bool = std::is_literal_type_v<_Type>> 16738fd1498Szrj struct _Uninitialized; 16838fd1498Szrj 16938fd1498Szrj template<typename _Type> 17038fd1498Szrj struct _Uninitialized<_Type, true> 17138fd1498Szrj { 17238fd1498Szrj template<typename... _Args> 17338fd1498Szrj constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) 17438fd1498Szrj : _M_storage(std::forward<_Args>(__args)...) 17538fd1498Szrj { } 17638fd1498Szrj 17738fd1498Szrj constexpr const _Type& _M_get() const & 17838fd1498Szrj { return _M_storage; } 17938fd1498Szrj 18038fd1498Szrj constexpr _Type& _M_get() & 18138fd1498Szrj { return _M_storage; } 18238fd1498Szrj 18338fd1498Szrj constexpr const _Type&& _M_get() const && 18438fd1498Szrj { return std::move(_M_storage); } 18538fd1498Szrj 18638fd1498Szrj constexpr _Type&& _M_get() && 18738fd1498Szrj { return std::move(_M_storage); } 18838fd1498Szrj 18938fd1498Szrj _Type _M_storage; 19038fd1498Szrj }; 19138fd1498Szrj 19238fd1498Szrj template<typename _Type> 19338fd1498Szrj struct _Uninitialized<_Type, false> 19438fd1498Szrj { 19538fd1498Szrj template<typename... _Args> 19638fd1498Szrj constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) 19738fd1498Szrj { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); } 19838fd1498Szrj 19938fd1498Szrj const _Type& _M_get() const & 20038fd1498Szrj { return *_M_storage._M_ptr(); } 20138fd1498Szrj 20238fd1498Szrj _Type& _M_get() & 20338fd1498Szrj { return *_M_storage._M_ptr(); } 20438fd1498Szrj 20538fd1498Szrj const _Type&& _M_get() const && 20638fd1498Szrj { return std::move(*_M_storage._M_ptr()); } 20738fd1498Szrj 20838fd1498Szrj _Type&& _M_get() && 20938fd1498Szrj { return std::move(*_M_storage._M_ptr()); } 21038fd1498Szrj 21138fd1498Szrj __gnu_cxx::__aligned_membuf<_Type> _M_storage; 21238fd1498Szrj }; 21338fd1498Szrj 21438fd1498Szrj template<typename _Ref> 21538fd1498Szrj _Ref __ref_cast(void* __ptr) 21638fd1498Szrj { 21738fd1498Szrj return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr)); 21838fd1498Szrj } 21938fd1498Szrj 22038fd1498Szrj template<typename _Union> 22138fd1498Szrj constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u) 22238fd1498Szrj { return std::forward<_Union>(__u)._M_first._M_get(); } 22338fd1498Szrj 22438fd1498Szrj template<size_t _Np, typename _Union> 22538fd1498Szrj constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u) 22638fd1498Szrj { 22738fd1498Szrj return __variant::__get(in_place_index<_Np-1>, 22838fd1498Szrj std::forward<_Union>(__u)._M_rest); 22938fd1498Szrj } 23038fd1498Szrj 23138fd1498Szrj // Returns the typed storage for __v. 23238fd1498Szrj template<size_t _Np, typename _Variant> 23338fd1498Szrj constexpr decltype(auto) __get(_Variant&& __v) 23438fd1498Szrj { 23538fd1498Szrj return __variant::__get(std::in_place_index<_Np>, 23638fd1498Szrj std::forward<_Variant>(__v)._M_u); 23738fd1498Szrj } 23838fd1498Szrj 23938fd1498Szrj // Various functions as "vtable" entries, where those vtables are used by 24038fd1498Szrj // polymorphic operations. 24138fd1498Szrj template<typename _Lhs, typename _Rhs> 24238fd1498Szrj void 24338fd1498Szrj __erased_ctor(void* __lhs, void* __rhs) 24438fd1498Szrj { 24538fd1498Szrj using _Type = remove_reference_t<_Lhs>; 24638fd1498Szrj ::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs)); 24738fd1498Szrj } 24838fd1498Szrj 24938fd1498Szrj template<typename _Variant, size_t _Np> 25038fd1498Szrj void 25138fd1498Szrj __erased_dtor(_Variant&& __v) 252*58e805e6Szrj { std::_Destroy(std::__addressof(__variant::__get<_Np>(__v))); } 25338fd1498Szrj 25438fd1498Szrj template<typename _Lhs, typename _Rhs> 25538fd1498Szrj void 25638fd1498Szrj __erased_assign(void* __lhs, void* __rhs) 25738fd1498Szrj { 25838fd1498Szrj __variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs); 25938fd1498Szrj } 26038fd1498Szrj 26138fd1498Szrj template<typename _Lhs, typename _Rhs> 26238fd1498Szrj void 26338fd1498Szrj __erased_swap(void* __lhs, void* __rhs) 26438fd1498Szrj { 26538fd1498Szrj using std::swap; 26638fd1498Szrj swap(__variant::__ref_cast<_Lhs>(__lhs), 26738fd1498Szrj __variant::__ref_cast<_Rhs>(__rhs)); 26838fd1498Szrj } 26938fd1498Szrj 27038fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 27138fd1498Szrj template<typename _Variant, size_t _Np> \ 27238fd1498Szrj constexpr bool \ 27338fd1498Szrj __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \ 27438fd1498Szrj { \ 27538fd1498Szrj return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \ 27638fd1498Szrj __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \ 27738fd1498Szrj } 27838fd1498Szrj 27938fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 28038fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 28138fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 28238fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 28338fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 28438fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 28538fd1498Szrj 28638fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 28738fd1498Szrj 28838fd1498Szrj template<typename _Tp> 28938fd1498Szrj size_t 29038fd1498Szrj __erased_hash(void* __t) 29138fd1498Szrj { 29238fd1498Szrj return std::hash<remove_cv_t<remove_reference_t<_Tp>>>{}( 29338fd1498Szrj __variant::__ref_cast<_Tp>(__t)); 29438fd1498Szrj } 29538fd1498Szrj 29638fd1498Szrj template<typename... _Types> 29738fd1498Szrj struct _Traits 29838fd1498Szrj { 29938fd1498Szrj static constexpr bool _S_default_ctor = 30038fd1498Szrj is_default_constructible_v<typename _Nth_type<0, _Types...>::type>; 30138fd1498Szrj static constexpr bool _S_copy_ctor = 30238fd1498Szrj (is_copy_constructible_v<_Types> && ...); 30338fd1498Szrj static constexpr bool _S_move_ctor = 30438fd1498Szrj (is_move_constructible_v<_Types> && ...); 30538fd1498Szrj static constexpr bool _S_copy_assign = 30638fd1498Szrj _S_copy_ctor && _S_move_ctor 30738fd1498Szrj && (is_copy_assignable_v<_Types> && ...); 30838fd1498Szrj static constexpr bool _S_move_assign = 30938fd1498Szrj _S_move_ctor 31038fd1498Szrj && (is_move_assignable_v<_Types> && ...); 31138fd1498Szrj 31238fd1498Szrj static constexpr bool _S_trivial_dtor = 31338fd1498Szrj (is_trivially_destructible_v<_Types> && ...); 31438fd1498Szrj static constexpr bool _S_trivial_copy_ctor = 31538fd1498Szrj (is_trivially_copy_constructible_v<_Types> && ...); 31638fd1498Szrj static constexpr bool _S_trivial_move_ctor = 31738fd1498Szrj (is_trivially_move_constructible_v<_Types> && ...); 31838fd1498Szrj static constexpr bool _S_trivial_copy_assign = 31938fd1498Szrj _S_trivial_dtor && (is_trivially_copy_assignable_v<_Types> && ...); 32038fd1498Szrj static constexpr bool _S_trivial_move_assign = 32138fd1498Szrj _S_trivial_dtor && (is_trivially_move_assignable_v<_Types> && ...); 32238fd1498Szrj 32338fd1498Szrj // The following nothrow traits are for non-trivial SMFs. Trivial SMFs 32438fd1498Szrj // are always nothrow. 32538fd1498Szrj static constexpr bool _S_nothrow_default_ctor = 32638fd1498Szrj is_nothrow_default_constructible_v< 32738fd1498Szrj typename _Nth_type<0, _Types...>::type>; 32838fd1498Szrj static constexpr bool _S_nothrow_copy_ctor = false; 32938fd1498Szrj static constexpr bool _S_nothrow_move_ctor = 33038fd1498Szrj (is_nothrow_move_constructible_v<_Types> && ...); 33138fd1498Szrj static constexpr bool _S_nothrow_copy_assign = false; 33238fd1498Szrj static constexpr bool _S_nothrow_move_assign = 33338fd1498Szrj _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...); 33438fd1498Szrj }; 33538fd1498Szrj 33638fd1498Szrj // Defines members and ctors. 33738fd1498Szrj template<typename... _Types> 33838fd1498Szrj union _Variadic_union { }; 33938fd1498Szrj 34038fd1498Szrj template<typename _First, typename... _Rest> 34138fd1498Szrj union _Variadic_union<_First, _Rest...> 34238fd1498Szrj { 34338fd1498Szrj constexpr _Variadic_union() : _M_rest() { } 34438fd1498Szrj 34538fd1498Szrj template<typename... _Args> 34638fd1498Szrj constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args) 34738fd1498Szrj : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) 34838fd1498Szrj { } 34938fd1498Szrj 35038fd1498Szrj template<size_t _Np, typename... _Args> 35138fd1498Szrj constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) 35238fd1498Szrj : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) 35338fd1498Szrj { } 35438fd1498Szrj 35538fd1498Szrj _Uninitialized<_First> _M_first; 35638fd1498Szrj _Variadic_union<_Rest...> _M_rest; 35738fd1498Szrj }; 35838fd1498Szrj 35938fd1498Szrj // Defines index and the dtor, possibly trivial. 36038fd1498Szrj template<bool __trivially_destructible, typename... _Types> 36138fd1498Szrj struct _Variant_storage; 36238fd1498Szrj 36338fd1498Szrj template <typename... _Types> 36438fd1498Szrj using __select_index = 36538fd1498Szrj typename __select_int::_Select_int_base<sizeof...(_Types) + 1, 36638fd1498Szrj unsigned char, 36738fd1498Szrj unsigned short>::type::value_type; 36838fd1498Szrj 36938fd1498Szrj template<typename... _Types> 37038fd1498Szrj struct _Variant_storage<false, _Types...> 37138fd1498Szrj { 37238fd1498Szrj template<size_t... __indices> 37338fd1498Szrj static constexpr void (*_S_vtable[])(const _Variant_storage&) = 37438fd1498Szrj { &__erased_dtor<const _Variant_storage&, __indices>... }; 37538fd1498Szrj 37638fd1498Szrj constexpr _Variant_storage() : _M_index(variant_npos) { } 37738fd1498Szrj 37838fd1498Szrj template<size_t _Np, typename... _Args> 37938fd1498Szrj constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) 38038fd1498Szrj : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), 38138fd1498Szrj _M_index(_Np) 38238fd1498Szrj { } 38338fd1498Szrj 38438fd1498Szrj template<size_t... __indices> 38538fd1498Szrj constexpr void _M_reset_impl(std::index_sequence<__indices...>) 38638fd1498Szrj { 38738fd1498Szrj if (_M_index != __index_type(variant_npos)) 38838fd1498Szrj _S_vtable<__indices...>[_M_index](*this); 38938fd1498Szrj } 39038fd1498Szrj 39138fd1498Szrj void _M_reset() 39238fd1498Szrj { 39338fd1498Szrj _M_reset_impl(std::index_sequence_for<_Types...>{}); 39438fd1498Szrj _M_index = variant_npos; 39538fd1498Szrj } 39638fd1498Szrj 39738fd1498Szrj ~_Variant_storage() 39838fd1498Szrj { _M_reset(); } 39938fd1498Szrj 40038fd1498Szrj void* 40138fd1498Szrj _M_storage() const 40238fd1498Szrj { 40338fd1498Szrj return const_cast<void*>(static_cast<const void*>( 40438fd1498Szrj std::addressof(_M_u))); 40538fd1498Szrj } 40638fd1498Szrj 40738fd1498Szrj constexpr bool 40838fd1498Szrj _M_valid() const noexcept 40938fd1498Szrj { 41038fd1498Szrj return this->_M_index != __index_type(variant_npos); 41138fd1498Szrj } 41238fd1498Szrj 41338fd1498Szrj _Variadic_union<_Types...> _M_u; 41438fd1498Szrj using __index_type = __select_index<_Types...>; 41538fd1498Szrj __index_type _M_index; 41638fd1498Szrj }; 41738fd1498Szrj 41838fd1498Szrj template<typename... _Types> 41938fd1498Szrj struct _Variant_storage<true, _Types...> 42038fd1498Szrj { 42138fd1498Szrj constexpr _Variant_storage() : _M_index(variant_npos) { } 42238fd1498Szrj 42338fd1498Szrj template<size_t _Np, typename... _Args> 42438fd1498Szrj constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) 42538fd1498Szrj : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), 42638fd1498Szrj _M_index(_Np) 42738fd1498Szrj { } 42838fd1498Szrj 42938fd1498Szrj void _M_reset() 43038fd1498Szrj { _M_index = variant_npos; } 43138fd1498Szrj 43238fd1498Szrj void* 43338fd1498Szrj _M_storage() const 43438fd1498Szrj { 43538fd1498Szrj return const_cast<void*>(static_cast<const void*>( 43638fd1498Szrj std::addressof(_M_u))); 43738fd1498Szrj } 43838fd1498Szrj 43938fd1498Szrj constexpr bool 44038fd1498Szrj _M_valid() const noexcept 44138fd1498Szrj { 44238fd1498Szrj return this->_M_index != __index_type(variant_npos); 44338fd1498Szrj } 44438fd1498Szrj 44538fd1498Szrj _Variadic_union<_Types...> _M_u; 44638fd1498Szrj using __index_type = __select_index<_Types...>; 44738fd1498Szrj __index_type _M_index; 44838fd1498Szrj }; 44938fd1498Szrj 45038fd1498Szrj template<typename... _Types> 45138fd1498Szrj using _Variant_storage_alias = 45238fd1498Szrj _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; 45338fd1498Szrj 45438fd1498Szrj // The following are (Copy|Move) (ctor|assign) layers for forwarding 45538fd1498Szrj // triviality and handling non-trivial SMF behaviors. 45638fd1498Szrj 45738fd1498Szrj template<bool, typename... _Types> 45838fd1498Szrj struct _Copy_ctor_base : _Variant_storage_alias<_Types...> 45938fd1498Szrj { 46038fd1498Szrj using _Base = _Variant_storage_alias<_Types...>; 46138fd1498Szrj using _Base::_Base; 46238fd1498Szrj 46338fd1498Szrj _Copy_ctor_base(const _Copy_ctor_base& __rhs) 46438fd1498Szrj noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor) 46538fd1498Szrj { 46638fd1498Szrj if (__rhs._M_valid()) 46738fd1498Szrj { 46838fd1498Szrj static constexpr void (*_S_vtable[])(void*, void*) = 46938fd1498Szrj { &__erased_ctor<_Types&, const _Types&>... }; 47038fd1498Szrj _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage()); 47138fd1498Szrj this->_M_index = __rhs._M_index; 47238fd1498Szrj } 47338fd1498Szrj } 47438fd1498Szrj 47538fd1498Szrj _Copy_ctor_base(_Copy_ctor_base&&) = default; 47638fd1498Szrj _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default; 47738fd1498Szrj _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default; 47838fd1498Szrj }; 47938fd1498Szrj 48038fd1498Szrj template<typename... _Types> 48138fd1498Szrj struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...> 48238fd1498Szrj { 48338fd1498Szrj using _Base = _Variant_storage_alias<_Types...>; 48438fd1498Szrj using _Base::_Base; 48538fd1498Szrj }; 48638fd1498Szrj 48738fd1498Szrj template<typename... _Types> 48838fd1498Szrj using _Copy_ctor_alias = 48938fd1498Szrj _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>; 49038fd1498Szrj 49138fd1498Szrj template<bool, typename... _Types> 49238fd1498Szrj struct _Move_ctor_base : _Copy_ctor_alias<_Types...> 49338fd1498Szrj { 49438fd1498Szrj using _Base = _Copy_ctor_alias<_Types...>; 49538fd1498Szrj using _Base::_Base; 49638fd1498Szrj 49738fd1498Szrj _Move_ctor_base(_Move_ctor_base&& __rhs) 49838fd1498Szrj noexcept(_Traits<_Types...>::_S_nothrow_move_ctor) 49938fd1498Szrj { 50038fd1498Szrj if (__rhs._M_valid()) 50138fd1498Szrj { 50238fd1498Szrj static constexpr void (*_S_vtable[])(void*, void*) = 50338fd1498Szrj { &__erased_ctor<_Types&, _Types&&>... }; 50438fd1498Szrj _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage()); 50538fd1498Szrj this->_M_index = __rhs._M_index; 50638fd1498Szrj } 50738fd1498Szrj } 50838fd1498Szrj 509*58e805e6Szrj void _M_destructive_move(_Move_ctor_base&& __rhs) 510*58e805e6Szrj { 511*58e805e6Szrj this->~_Move_ctor_base(); 512*58e805e6Szrj __try 513*58e805e6Szrj { 514*58e805e6Szrj ::new (this) _Move_ctor_base(std::move(__rhs)); 515*58e805e6Szrj } 516*58e805e6Szrj __catch (...) 517*58e805e6Szrj { 518*58e805e6Szrj this->_M_index = variant_npos; 519*58e805e6Szrj __throw_exception_again; 520*58e805e6Szrj } 521*58e805e6Szrj } 522*58e805e6Szrj 52338fd1498Szrj _Move_ctor_base(const _Move_ctor_base&) = default; 52438fd1498Szrj _Move_ctor_base& operator=(const _Move_ctor_base&) = default; 52538fd1498Szrj _Move_ctor_base& operator=(_Move_ctor_base&&) = default; 52638fd1498Szrj }; 52738fd1498Szrj 52838fd1498Szrj template<typename... _Types> 52938fd1498Szrj struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...> 53038fd1498Szrj { 53138fd1498Szrj using _Base = _Copy_ctor_alias<_Types...>; 53238fd1498Szrj using _Base::_Base; 533*58e805e6Szrj 534*58e805e6Szrj void _M_destructive_move(_Move_ctor_base&& __rhs) 535*58e805e6Szrj { 536*58e805e6Szrj this->~_Move_ctor_base(); 537*58e805e6Szrj ::new (this) _Move_ctor_base(std::move(__rhs)); 538*58e805e6Szrj } 53938fd1498Szrj }; 54038fd1498Szrj 54138fd1498Szrj template<typename... _Types> 54238fd1498Szrj using _Move_ctor_alias = 54338fd1498Szrj _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>; 54438fd1498Szrj 54538fd1498Szrj template<bool, typename... _Types> 54638fd1498Szrj struct _Copy_assign_base : _Move_ctor_alias<_Types...> 54738fd1498Szrj { 54838fd1498Szrj using _Base = _Move_ctor_alias<_Types...>; 54938fd1498Szrj using _Base::_Base; 55038fd1498Szrj 55138fd1498Szrj _Copy_assign_base& 55238fd1498Szrj operator=(const _Copy_assign_base& __rhs) 55338fd1498Szrj noexcept(_Traits<_Types...>::_S_nothrow_copy_assign) 55438fd1498Szrj { 55538fd1498Szrj if (this->_M_index == __rhs._M_index) 55638fd1498Szrj { 55738fd1498Szrj if (__rhs._M_valid()) 55838fd1498Szrj { 55938fd1498Szrj static constexpr void (*_S_vtable[])(void*, void*) = 56038fd1498Szrj { &__erased_assign<_Types&, const _Types&>... }; 561*58e805e6Szrj _S_vtable[__rhs._M_index](this->_M_storage(), 562*58e805e6Szrj __rhs._M_storage()); 56338fd1498Szrj } 56438fd1498Szrj } 56538fd1498Szrj else 56638fd1498Szrj { 56738fd1498Szrj _Copy_assign_base __tmp(__rhs); 568*58e805e6Szrj this->_M_destructive_move(std::move(__tmp)); 56938fd1498Szrj } 57038fd1498Szrj __glibcxx_assert(this->_M_index == __rhs._M_index); 57138fd1498Szrj return *this; 57238fd1498Szrj } 57338fd1498Szrj 57438fd1498Szrj _Copy_assign_base(const _Copy_assign_base&) = default; 57538fd1498Szrj _Copy_assign_base(_Copy_assign_base&&) = default; 57638fd1498Szrj _Copy_assign_base& operator=(_Copy_assign_base&&) = default; 57738fd1498Szrj }; 57838fd1498Szrj 57938fd1498Szrj template<typename... _Types> 58038fd1498Szrj struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...> 58138fd1498Szrj { 58238fd1498Szrj using _Base = _Move_ctor_alias<_Types...>; 58338fd1498Szrj using _Base::_Base; 58438fd1498Szrj }; 58538fd1498Szrj 58638fd1498Szrj template<typename... _Types> 58738fd1498Szrj using _Copy_assign_alias = 58838fd1498Szrj _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, 58938fd1498Szrj _Types...>; 59038fd1498Szrj 59138fd1498Szrj template<bool, typename... _Types> 59238fd1498Szrj struct _Move_assign_base : _Copy_assign_alias<_Types...> 59338fd1498Szrj { 59438fd1498Szrj using _Base = _Copy_assign_alias<_Types...>; 59538fd1498Szrj using _Base::_Base; 59638fd1498Szrj 59738fd1498Szrj _Move_assign_base& 59838fd1498Szrj operator=(_Move_assign_base&& __rhs) 59938fd1498Szrj noexcept(_Traits<_Types...>::_S_nothrow_move_assign) 60038fd1498Szrj { 60138fd1498Szrj if (this->_M_index == __rhs._M_index) 60238fd1498Szrj { 60338fd1498Szrj if (__rhs._M_valid()) 60438fd1498Szrj { 60538fd1498Szrj static constexpr void (*_S_vtable[])(void*, void*) = 60638fd1498Szrj { &__erased_assign<_Types&, _Types&&>... }; 60738fd1498Szrj _S_vtable[__rhs._M_index] 60838fd1498Szrj (this->_M_storage(), __rhs._M_storage()); 60938fd1498Szrj } 61038fd1498Szrj } 61138fd1498Szrj else 61238fd1498Szrj { 61338fd1498Szrj _Move_assign_base __tmp(std::move(__rhs)); 614*58e805e6Szrj this->_M_destructive_move(std::move(__tmp)); 61538fd1498Szrj } 61638fd1498Szrj __glibcxx_assert(this->_M_index == __rhs._M_index); 61738fd1498Szrj return *this; 61838fd1498Szrj } 61938fd1498Szrj 62038fd1498Szrj _Move_assign_base(const _Move_assign_base&) = default; 62138fd1498Szrj _Move_assign_base(_Move_assign_base&&) = default; 62238fd1498Szrj _Move_assign_base& operator=(const _Move_assign_base&) = default; 62338fd1498Szrj }; 62438fd1498Szrj 62538fd1498Szrj template<typename... _Types> 62638fd1498Szrj struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...> 62738fd1498Szrj { 62838fd1498Szrj using _Base = _Copy_assign_alias<_Types...>; 62938fd1498Szrj using _Base::_Base; 63038fd1498Szrj }; 63138fd1498Szrj 63238fd1498Szrj template<typename... _Types> 63338fd1498Szrj using _Move_assign_alias = 63438fd1498Szrj _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, 63538fd1498Szrj _Types...>; 63638fd1498Szrj 63738fd1498Szrj template<typename... _Types> 63838fd1498Szrj struct _Variant_base : _Move_assign_alias<_Types...> 63938fd1498Szrj { 64038fd1498Szrj using _Base = _Move_assign_alias<_Types...>; 64138fd1498Szrj 64238fd1498Szrj constexpr 64338fd1498Szrj _Variant_base() 64438fd1498Szrj noexcept(_Traits<_Types...>::_S_nothrow_default_ctor) 64538fd1498Szrj : _Variant_base(in_place_index<0>) { } 64638fd1498Szrj 64738fd1498Szrj template<size_t _Np, typename... _Args> 64838fd1498Szrj constexpr explicit 64938fd1498Szrj _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) 65038fd1498Szrj : _Base(__i, std::forward<_Args>(__args)...) 65138fd1498Szrj { } 65238fd1498Szrj 65338fd1498Szrj _Variant_base(const _Variant_base&) = default; 65438fd1498Szrj _Variant_base(_Variant_base&&) = default; 65538fd1498Szrj _Variant_base& operator=(const _Variant_base&) = default; 65638fd1498Szrj _Variant_base& operator=(_Variant_base&&) = default; 65738fd1498Szrj }; 65838fd1498Szrj 65938fd1498Szrj // For how many times does _Tp appear in _Tuple? 66038fd1498Szrj template<typename _Tp, typename _Tuple> 66138fd1498Szrj struct __tuple_count; 66238fd1498Szrj 66338fd1498Szrj template<typename _Tp, typename _Tuple> 66438fd1498Szrj inline constexpr size_t __tuple_count_v = 66538fd1498Szrj __tuple_count<_Tp, _Tuple>::value; 66638fd1498Szrj 66738fd1498Szrj template<typename _Tp, typename... _Types> 66838fd1498Szrj struct __tuple_count<_Tp, tuple<_Types...>> 66938fd1498Szrj : integral_constant<size_t, 0> { }; 67038fd1498Szrj 67138fd1498Szrj template<typename _Tp, typename _First, typename... _Rest> 67238fd1498Szrj struct __tuple_count<_Tp, tuple<_First, _Rest...>> 67338fd1498Szrj : integral_constant< 67438fd1498Szrj size_t, 67538fd1498Szrj __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; 67638fd1498Szrj 67738fd1498Szrj // TODO: Reuse this in <tuple> ? 67838fd1498Szrj template<typename _Tp, typename... _Types> 67938fd1498Szrj inline constexpr bool __exactly_once = 68038fd1498Szrj __tuple_count_v<_Tp, tuple<_Types...>> == 1; 68138fd1498Szrj 68238fd1498Szrj // Takes _Types and create an overloaded _S_fun for each type. 68338fd1498Szrj // If a type appears more than once in _Types, create only one overload. 68438fd1498Szrj template<typename... _Types> 68538fd1498Szrj struct __overload_set 68638fd1498Szrj { static void _S_fun(); }; 68738fd1498Szrj 68838fd1498Szrj template<typename _First, typename... _Rest> 68938fd1498Szrj struct __overload_set<_First, _Rest...> : __overload_set<_Rest...> 69038fd1498Szrj { 69138fd1498Szrj using __overload_set<_Rest...>::_S_fun; 69238fd1498Szrj static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 69338fd1498Szrj }; 69438fd1498Szrj 69538fd1498Szrj template<typename... _Rest> 69638fd1498Szrj struct __overload_set<void, _Rest...> : __overload_set<_Rest...> 69738fd1498Szrj { 69838fd1498Szrj using __overload_set<_Rest...>::_S_fun; 69938fd1498Szrj }; 70038fd1498Szrj 70138fd1498Szrj // Helper for variant(_Tp&&) and variant::operator=(_Tp&&). 70238fd1498Szrj // __accepted_index maps the arbitrary _Tp to an alternative type in _Variant. 70338fd1498Szrj template<typename _Tp, typename _Variant, typename = void> 70438fd1498Szrj struct __accepted_index 70538fd1498Szrj { static constexpr size_t value = variant_npos; }; 70638fd1498Szrj 70738fd1498Szrj template<typename _Tp, typename... _Types> 70838fd1498Szrj struct __accepted_index< 70938fd1498Szrj _Tp, variant<_Types...>, 71038fd1498Szrj decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()), 71138fd1498Szrj std::declval<void>())> 71238fd1498Szrj { 71338fd1498Szrj static constexpr size_t value = sizeof...(_Types) - 1 71438fd1498Szrj - decltype(__overload_set<_Types...>:: 71538fd1498Szrj _S_fun(std::declval<_Tp>()))::value; 71638fd1498Szrj }; 71738fd1498Szrj 71838fd1498Szrj // Returns the raw storage for __v. 71938fd1498Szrj template<typename _Variant> 72038fd1498Szrj void* __get_storage(_Variant&& __v) 72138fd1498Szrj { return __v._M_storage(); } 72238fd1498Szrj 72338fd1498Szrj // Used for storing multi-dimensional vtable. 72438fd1498Szrj template<typename _Tp, size_t... _Dimensions> 72538fd1498Szrj struct _Multi_array 72638fd1498Szrj { 72738fd1498Szrj constexpr const _Tp& 72838fd1498Szrj _M_access() const 72938fd1498Szrj { return _M_data; } 73038fd1498Szrj 73138fd1498Szrj _Tp _M_data; 73238fd1498Szrj }; 73338fd1498Szrj 73438fd1498Szrj template<typename _Tp, size_t __first, size_t... __rest> 73538fd1498Szrj struct _Multi_array<_Tp, __first, __rest...> 73638fd1498Szrj { 73738fd1498Szrj template<typename... _Args> 73838fd1498Szrj constexpr const _Tp& 73938fd1498Szrj _M_access(size_t __first_index, _Args... __rest_indices) const 74038fd1498Szrj { return _M_arr[__first_index]._M_access(__rest_indices...); } 74138fd1498Szrj 74238fd1498Szrj _Multi_array<_Tp, __rest...> _M_arr[__first]; 74338fd1498Szrj }; 74438fd1498Szrj 74538fd1498Szrj // Creates a multi-dimensional vtable recursively. 74638fd1498Szrj // 74738fd1498Szrj // For example, 74838fd1498Szrj // visit([](auto, auto){}, 74938fd1498Szrj // variant<int, char>(), // typedef'ed as V1 75038fd1498Szrj // variant<float, double, long double>()) // typedef'ed as V2 75138fd1498Szrj // will trigger instantiations of: 75238fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>, 75338fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<>> 75438fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>, 75538fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<0>> 75638fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 75738fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<0, 0>> 75838fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 75938fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<0, 1>> 76038fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 76138fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<0, 2>> 76238fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>, 76338fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<1>> 76438fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 76538fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<1, 0>> 76638fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 76738fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<1, 1>> 76838fd1498Szrj // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>, 76938fd1498Szrj // tuple<V1&&, V2&&>, std::index_sequence<1, 2>> 77038fd1498Szrj // The returned multi-dimensional vtable can be fast accessed by the visitor 77138fd1498Szrj // using index calculation. 77238fd1498Szrj template<typename _Array_type, typename _Variant_tuple, typename _Index_seq> 77338fd1498Szrj struct __gen_vtable_impl; 77438fd1498Szrj 77538fd1498Szrj template<typename _Result_type, typename _Visitor, size_t... __dimensions, 77638fd1498Szrj typename... _Variants, size_t... __indices> 77738fd1498Szrj struct __gen_vtable_impl< 77838fd1498Szrj _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, 77938fd1498Szrj tuple<_Variants...>, std::index_sequence<__indices...>> 78038fd1498Szrj { 78138fd1498Szrj using _Next = 78238fd1498Szrj remove_reference_t<typename _Nth_type<sizeof...(__indices), 78338fd1498Szrj _Variants...>::type>; 78438fd1498Szrj using _Array_type = 78538fd1498Szrj _Multi_array<_Result_type (*)(_Visitor, _Variants...), 78638fd1498Szrj __dimensions...>; 78738fd1498Szrj 78838fd1498Szrj static constexpr _Array_type 78938fd1498Szrj _S_apply() 79038fd1498Szrj { 79138fd1498Szrj _Array_type __vtable{}; 79238fd1498Szrj _S_apply_all_alts( 79338fd1498Szrj __vtable, make_index_sequence<variant_size_v<_Next>>()); 79438fd1498Szrj return __vtable; 79538fd1498Szrj } 79638fd1498Szrj 79738fd1498Szrj template<size_t... __var_indices> 79838fd1498Szrj static constexpr void 79938fd1498Szrj _S_apply_all_alts(_Array_type& __vtable, 80038fd1498Szrj std::index_sequence<__var_indices...>) 80138fd1498Szrj { 80238fd1498Szrj (_S_apply_single_alt<__var_indices>( 80338fd1498Szrj __vtable._M_arr[__var_indices]), ...); 80438fd1498Szrj } 80538fd1498Szrj 80638fd1498Szrj template<size_t __index, typename _Tp> 80738fd1498Szrj static constexpr void 80838fd1498Szrj _S_apply_single_alt(_Tp& __element) 80938fd1498Szrj { 81038fd1498Szrj using _Alternative = variant_alternative_t<__index, _Next>; 81138fd1498Szrj __element = __gen_vtable_impl< 81238fd1498Szrj remove_reference_t< 81338fd1498Szrj decltype(__element)>, tuple<_Variants...>, 81438fd1498Szrj std::index_sequence<__indices..., __index>>::_S_apply(); 81538fd1498Szrj } 81638fd1498Szrj }; 81738fd1498Szrj 81838fd1498Szrj template<typename _Result_type, typename _Visitor, typename... _Variants, 81938fd1498Szrj size_t... __indices> 82038fd1498Szrj struct __gen_vtable_impl< 82138fd1498Szrj _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, 82238fd1498Szrj tuple<_Variants...>, std::index_sequence<__indices...>> 82338fd1498Szrj { 82438fd1498Szrj using _Array_type = 82538fd1498Szrj _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>; 82638fd1498Szrj 82738fd1498Szrj decltype(auto) 82838fd1498Szrj static constexpr __visit_invoke(_Visitor&& __visitor, _Variants... __vars) 82938fd1498Szrj { 830*58e805e6Szrj return std::__invoke(std::forward<_Visitor>(__visitor), 831*58e805e6Szrj std::get<__indices>(std::forward<_Variants>(__vars))...); 83238fd1498Szrj } 83338fd1498Szrj 83438fd1498Szrj static constexpr auto 83538fd1498Szrj _S_apply() 83638fd1498Szrj { return _Array_type{&__visit_invoke}; } 83738fd1498Szrj }; 83838fd1498Szrj 83938fd1498Szrj template<typename _Result_type, typename _Visitor, typename... _Variants> 84038fd1498Szrj struct __gen_vtable 84138fd1498Szrj { 84238fd1498Szrj using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...); 84338fd1498Szrj using _Array_type = 84438fd1498Szrj _Multi_array<_Func_ptr, 84538fd1498Szrj variant_size_v<remove_reference_t<_Variants>>...>; 84638fd1498Szrj 84738fd1498Szrj static constexpr _Array_type 84838fd1498Szrj _S_apply() 84938fd1498Szrj { 85038fd1498Szrj return __gen_vtable_impl<_Array_type, tuple<_Variants...>, 85138fd1498Szrj std::index_sequence<>>::_S_apply(); 85238fd1498Szrj } 85338fd1498Szrj 85438fd1498Szrj static constexpr auto _S_vtable = _S_apply(); 85538fd1498Szrj }; 85638fd1498Szrj 85738fd1498Szrj template<size_t _Np, typename _Tp> 85838fd1498Szrj struct _Base_dedup : public _Tp { }; 85938fd1498Szrj 86038fd1498Szrj template<typename _Variant, typename __indices> 86138fd1498Szrj struct _Variant_hash_base; 86238fd1498Szrj 86338fd1498Szrj template<typename... _Types, size_t... __indices> 86438fd1498Szrj struct _Variant_hash_base<variant<_Types...>, 86538fd1498Szrj std::index_sequence<__indices...>> 86638fd1498Szrj : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { }; 86738fd1498Szrj 86838fd1498Szrj} // namespace __variant 86938fd1498Szrj} // namespace __detail 87038fd1498Szrj 87138fd1498Szrj template<typename _Tp, typename... _Types> 87238fd1498Szrj inline constexpr bool holds_alternative(const variant<_Types...>& __v) 87338fd1498Szrj noexcept 87438fd1498Szrj { 87538fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 87638fd1498Szrj "T should occur for exactly once in alternatives"); 87738fd1498Szrj return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>; 87838fd1498Szrj } 87938fd1498Szrj 88038fd1498Szrj template<typename _Tp, typename... _Types> 88138fd1498Szrj constexpr inline _Tp& get(variant<_Types...>& __v) 88238fd1498Szrj { 88338fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 88438fd1498Szrj "T should occur for exactly once in alternatives"); 88538fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 88638fd1498Szrj return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); 88738fd1498Szrj } 88838fd1498Szrj 88938fd1498Szrj template<typename _Tp, typename... _Types> 89038fd1498Szrj constexpr inline _Tp&& get(variant<_Types...>&& __v) 89138fd1498Szrj { 89238fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 89338fd1498Szrj "T should occur for exactly once in alternatives"); 89438fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 89538fd1498Szrj return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( 89638fd1498Szrj std::move(__v)); 89738fd1498Szrj } 89838fd1498Szrj 89938fd1498Szrj template<typename _Tp, typename... _Types> 90038fd1498Szrj constexpr inline const _Tp& get(const variant<_Types...>& __v) 90138fd1498Szrj { 90238fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 90338fd1498Szrj "T should occur for exactly once in alternatives"); 90438fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 90538fd1498Szrj return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); 90638fd1498Szrj } 90738fd1498Szrj 90838fd1498Szrj template<typename _Tp, typename... _Types> 90938fd1498Szrj constexpr inline const _Tp&& get(const variant<_Types...>&& __v) 91038fd1498Szrj { 91138fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 91238fd1498Szrj "T should occur for exactly once in alternatives"); 91338fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 91438fd1498Szrj return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( 91538fd1498Szrj std::move(__v)); 91638fd1498Szrj } 91738fd1498Szrj 91838fd1498Szrj template<size_t _Np, typename... _Types> 91938fd1498Szrj constexpr inline 92038fd1498Szrj add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>> 92138fd1498Szrj get_if(variant<_Types...>* __ptr) noexcept 92238fd1498Szrj { 92338fd1498Szrj using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; 92438fd1498Szrj static_assert(_Np < sizeof...(_Types), 92538fd1498Szrj "The index should be in [0, number of alternatives)"); 92638fd1498Szrj static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void"); 92738fd1498Szrj if (__ptr && __ptr->index() == _Np) 92838fd1498Szrj return &__detail::__variant::__get<_Np>(*__ptr); 92938fd1498Szrj return nullptr; 93038fd1498Szrj } 93138fd1498Szrj 93238fd1498Szrj template<size_t _Np, typename... _Types> 93338fd1498Szrj constexpr inline 93438fd1498Szrj add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>> 93538fd1498Szrj get_if(const variant<_Types...>* __ptr) noexcept 93638fd1498Szrj { 93738fd1498Szrj using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; 93838fd1498Szrj static_assert(_Np < sizeof...(_Types), 93938fd1498Szrj "The index should be in [0, number of alternatives)"); 94038fd1498Szrj static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void"); 94138fd1498Szrj if (__ptr && __ptr->index() == _Np) 94238fd1498Szrj return &__detail::__variant::__get<_Np>(*__ptr); 94338fd1498Szrj return nullptr; 94438fd1498Szrj } 94538fd1498Szrj 94638fd1498Szrj template<typename _Tp, typename... _Types> 94738fd1498Szrj constexpr inline add_pointer_t<_Tp> 94838fd1498Szrj get_if(variant<_Types...>* __ptr) noexcept 94938fd1498Szrj { 95038fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 95138fd1498Szrj "T should occur for exactly once in alternatives"); 95238fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 95338fd1498Szrj return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( 95438fd1498Szrj __ptr); 95538fd1498Szrj } 95638fd1498Szrj 95738fd1498Szrj template<typename _Tp, typename... _Types> 95838fd1498Szrj constexpr inline add_pointer_t<const _Tp> 95938fd1498Szrj get_if(const variant<_Types...>* __ptr) 96038fd1498Szrj noexcept 96138fd1498Szrj { 96238fd1498Szrj static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, 96338fd1498Szrj "T should occur for exactly once in alternatives"); 96438fd1498Szrj static_assert(!is_void_v<_Tp>, "_Tp should not be void"); 96538fd1498Szrj return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( 96638fd1498Szrj __ptr); 96738fd1498Szrj } 96838fd1498Szrj 96938fd1498Szrj struct monostate { }; 97038fd1498Szrj 97138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 97238fd1498Szrj template<typename... _Types> \ 97338fd1498Szrj constexpr bool operator __OP(const variant<_Types...>& __lhs, \ 97438fd1498Szrj const variant<_Types...>& __rhs) \ 97538fd1498Szrj { \ 97638fd1498Szrj return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \ 97738fd1498Szrj } \ 97838fd1498Szrj\ 97938fd1498Szrj constexpr bool operator __OP(monostate, monostate) noexcept \ 98038fd1498Szrj { return 0 __OP 0; } 98138fd1498Szrj 98238fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 98338fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 98438fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 98538fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 98638fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 98738fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 98838fd1498Szrj 98938fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 99038fd1498Szrj 99138fd1498Szrj template<typename _Visitor, typename... _Variants> 99238fd1498Szrj constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); 99338fd1498Szrj 99438fd1498Szrj template<typename... _Types> 99538fd1498Szrj inline enable_if_t<(is_move_constructible_v<_Types> && ...) 99638fd1498Szrj && (is_swappable_v<_Types> && ...)> 99738fd1498Szrj swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) 99838fd1498Szrj noexcept(noexcept(__lhs.swap(__rhs))) 99938fd1498Szrj { __lhs.swap(__rhs); } 100038fd1498Szrj 100138fd1498Szrj template<typename... _Types> 100238fd1498Szrj enable_if_t<!((is_move_constructible_v<_Types> && ...) 100338fd1498Szrj && (is_swappable_v<_Types> && ...))> 100438fd1498Szrj swap(variant<_Types...>&, variant<_Types...>&) = delete; 100538fd1498Szrj 100638fd1498Szrj class bad_variant_access : public exception 100738fd1498Szrj { 100838fd1498Szrj public: 100938fd1498Szrj bad_variant_access() noexcept : _M_reason("Unknown reason") { } 101038fd1498Szrj const char* what() const noexcept override 101138fd1498Szrj { return _M_reason; } 101238fd1498Szrj 101338fd1498Szrj private: 101438fd1498Szrj bad_variant_access(const char* __reason) : _M_reason(__reason) { } 101538fd1498Szrj 101638fd1498Szrj const char* _M_reason; 101738fd1498Szrj 101838fd1498Szrj friend void __throw_bad_variant_access(const char* __what); 101938fd1498Szrj }; 102038fd1498Szrj 102138fd1498Szrj inline void 102238fd1498Szrj __throw_bad_variant_access(const char* __what) 102338fd1498Szrj { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); } 102438fd1498Szrj 102538fd1498Szrj template<typename... _Types> 102638fd1498Szrj class variant 102738fd1498Szrj : private __detail::__variant::_Variant_base<_Types...>, 102838fd1498Szrj private _Enable_default_constructor< 102938fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_default_ctor, 103038fd1498Szrj variant<_Types...>>, 103138fd1498Szrj private _Enable_copy_move< 103238fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_copy_ctor, 103338fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_copy_assign, 103438fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_move_ctor, 103538fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_move_assign, 103638fd1498Szrj variant<_Types...>> 103738fd1498Szrj { 103838fd1498Szrj private: 103938fd1498Szrj static_assert(sizeof...(_Types) > 0, 104038fd1498Szrj "variant must have at least one alternative"); 104138fd1498Szrj static_assert(!(std::is_reference_v<_Types> || ...), 104238fd1498Szrj "variant must have no reference alternative"); 104338fd1498Szrj static_assert(!(std::is_void_v<_Types> || ...), 104438fd1498Szrj "variant must have no void alternative"); 104538fd1498Szrj 104638fd1498Szrj using _Base = __detail::__variant::_Variant_base<_Types...>; 104738fd1498Szrj using _Default_ctor_enabler = 104838fd1498Szrj _Enable_default_constructor< 104938fd1498Szrj __detail::__variant::_Traits<_Types...>::_S_default_ctor, 105038fd1498Szrj variant<_Types...>>; 105138fd1498Szrj 105238fd1498Szrj template<typename _Tp> 105338fd1498Szrj static constexpr bool 105438fd1498Szrj __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; 105538fd1498Szrj 105638fd1498Szrj template<typename _Tp> 105738fd1498Szrj static constexpr size_t __accepted_index = 105838fd1498Szrj __detail::__variant::__accepted_index<_Tp&&, variant>::value; 105938fd1498Szrj 106038fd1498Szrj template<size_t _Np, bool = _Np < sizeof...(_Types)> 106138fd1498Szrj struct __to_type_impl; 106238fd1498Szrj 106338fd1498Szrj template<size_t _Np> 106438fd1498Szrj struct __to_type_impl<_Np, true> 106538fd1498Szrj { using type = variant_alternative_t<_Np, variant>; }; 106638fd1498Szrj 106738fd1498Szrj template<size_t _Np> 106838fd1498Szrj using __to_type = typename __to_type_impl<_Np>::type; 106938fd1498Szrj 107038fd1498Szrj template<typename _Tp> 107138fd1498Szrj using __accepted_type = __to_type<__accepted_index<_Tp>>; 107238fd1498Szrj 107338fd1498Szrj template<typename _Tp> 107438fd1498Szrj static constexpr size_t __index_of = 107538fd1498Szrj __detail::__variant::__index_of_v<_Tp, _Types...>; 107638fd1498Szrj 107738fd1498Szrj using _Traits = __detail::__variant::_Traits<_Types...>; 107838fd1498Szrj 107938fd1498Szrj public: 108038fd1498Szrj variant() = default; 108138fd1498Szrj variant(const variant& __rhs) = default; 108238fd1498Szrj variant(variant&&) = default; 108338fd1498Szrj variant& operator=(const variant&) = default; 108438fd1498Szrj variant& operator=(variant&&) = default; 108538fd1498Szrj ~variant() = default; 108638fd1498Szrj 108738fd1498Szrj template<typename _Tp, 108838fd1498Szrj typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>, 108938fd1498Szrj typename = enable_if_t<(sizeof...(_Types)>0)>, 109038fd1498Szrj typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>> 109138fd1498Szrj && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>> 109238fd1498Szrj constexpr 109338fd1498Szrj variant(_Tp&& __t) 109438fd1498Szrj noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>) 109538fd1498Szrj : variant(in_place_index<__accepted_index<_Tp&&>>, 109638fd1498Szrj std::forward<_Tp>(__t)) 109738fd1498Szrj { __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); } 109838fd1498Szrj 109938fd1498Szrj template<typename _Tp, typename... _Args, 110038fd1498Szrj typename = enable_if_t<__exactly_once<_Tp> 110138fd1498Szrj && is_constructible_v<_Tp, _Args&&...>>> 110238fd1498Szrj constexpr explicit 110338fd1498Szrj variant(in_place_type_t<_Tp>, _Args&&... __args) 110438fd1498Szrj : variant(in_place_index<__index_of<_Tp>>, 110538fd1498Szrj std::forward<_Args>(__args)...) 110638fd1498Szrj { __glibcxx_assert(holds_alternative<_Tp>(*this)); } 110738fd1498Szrj 110838fd1498Szrj template<typename _Tp, typename _Up, typename... _Args, 110938fd1498Szrj typename = enable_if_t<__exactly_once<_Tp> 111038fd1498Szrj && is_constructible_v< 111138fd1498Szrj _Tp, initializer_list<_Up>&, _Args&&...>>> 111238fd1498Szrj constexpr explicit 111338fd1498Szrj variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, 111438fd1498Szrj _Args&&... __args) 111538fd1498Szrj : variant(in_place_index<__index_of<_Tp>>, __il, 111638fd1498Szrj std::forward<_Args>(__args)...) 111738fd1498Szrj { __glibcxx_assert(holds_alternative<_Tp>(*this)); } 111838fd1498Szrj 111938fd1498Szrj template<size_t _Np, typename... _Args, 112038fd1498Szrj typename = enable_if_t< 112138fd1498Szrj is_constructible_v<__to_type<_Np>, _Args&&...>>> 112238fd1498Szrj constexpr explicit 112338fd1498Szrj variant(in_place_index_t<_Np>, _Args&&... __args) 112438fd1498Szrj : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...), 112538fd1498Szrj _Default_ctor_enabler(_Enable_default_constructor_tag{}) 112638fd1498Szrj { __glibcxx_assert(index() == _Np); } 112738fd1498Szrj 112838fd1498Szrj template<size_t _Np, typename _Up, typename... _Args, 112938fd1498Szrj typename = enable_if_t<is_constructible_v<__to_type<_Np>, 113038fd1498Szrj initializer_list<_Up>&, _Args&&...>>> 113138fd1498Szrj constexpr explicit 113238fd1498Szrj variant(in_place_index_t<_Np>, initializer_list<_Up> __il, 113338fd1498Szrj _Args&&... __args) 113438fd1498Szrj : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...), 113538fd1498Szrj _Default_ctor_enabler(_Enable_default_constructor_tag{}) 113638fd1498Szrj { __glibcxx_assert(index() == _Np); } 113738fd1498Szrj 113838fd1498Szrj template<typename _Tp> 113938fd1498Szrj enable_if_t<__exactly_once<__accepted_type<_Tp&&>> 114038fd1498Szrj && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&> 114138fd1498Szrj && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&> 114238fd1498Szrj && !is_same_v<decay_t<_Tp>, variant>, variant&> 114338fd1498Szrj operator=(_Tp&& __rhs) 114438fd1498Szrj noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&> 114538fd1498Szrj && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>) 114638fd1498Szrj { 114738fd1498Szrj constexpr auto __index = __accepted_index<_Tp&&>; 114838fd1498Szrj if (index() == __index) 114938fd1498Szrj std::get<__index>(*this) = std::forward<_Tp>(__rhs); 115038fd1498Szrj else 115138fd1498Szrj this->emplace<__index>(std::forward<_Tp>(__rhs)); 115238fd1498Szrj __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); 115338fd1498Szrj return *this; 115438fd1498Szrj } 115538fd1498Szrj 115638fd1498Szrj template<typename _Tp, typename... _Args> 115738fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>, 115838fd1498Szrj _Tp&> 115938fd1498Szrj emplace(_Args&&... __args) 116038fd1498Szrj { 116138fd1498Szrj auto& ret = 116238fd1498Szrj this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...); 116338fd1498Szrj __glibcxx_assert(holds_alternative<_Tp>(*this)); 116438fd1498Szrj return ret; 116538fd1498Szrj } 116638fd1498Szrj 116738fd1498Szrj template<typename _Tp, typename _Up, typename... _Args> 116838fd1498Szrj enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> 116938fd1498Szrj && __exactly_once<_Tp>, 117038fd1498Szrj _Tp&> 117138fd1498Szrj emplace(initializer_list<_Up> __il, _Args&&... __args) 117238fd1498Szrj { 117338fd1498Szrj auto& ret = 117438fd1498Szrj this->emplace<__index_of<_Tp>>(__il, 117538fd1498Szrj std::forward<_Args>(__args)...); 117638fd1498Szrj __glibcxx_assert(holds_alternative<_Tp>(*this)); 117738fd1498Szrj return ret; 117838fd1498Szrj } 117938fd1498Szrj 118038fd1498Szrj template<size_t _Np, typename... _Args> 118138fd1498Szrj enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>, 118238fd1498Szrj _Args...>, 118338fd1498Szrj variant_alternative_t<_Np, variant>&> 118438fd1498Szrj emplace(_Args&&... __args) 118538fd1498Szrj { 118638fd1498Szrj static_assert(_Np < sizeof...(_Types), 118738fd1498Szrj "The index should be in [0, number of alternatives)"); 118838fd1498Szrj this->~variant(); 118938fd1498Szrj __try 119038fd1498Szrj { 119138fd1498Szrj ::new (this) variant(in_place_index<_Np>, 119238fd1498Szrj std::forward<_Args>(__args)...); 119338fd1498Szrj } 119438fd1498Szrj __catch (...) 119538fd1498Szrj { 119638fd1498Szrj this->_M_index = variant_npos; 119738fd1498Szrj __throw_exception_again; 119838fd1498Szrj } 119938fd1498Szrj __glibcxx_assert(index() == _Np); 120038fd1498Szrj return std::get<_Np>(*this); 120138fd1498Szrj } 120238fd1498Szrj 120338fd1498Szrj template<size_t _Np, typename _Up, typename... _Args> 120438fd1498Szrj enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>, 120538fd1498Szrj initializer_list<_Up>&, _Args...>, 120638fd1498Szrj variant_alternative_t<_Np, variant>&> 120738fd1498Szrj emplace(initializer_list<_Up> __il, _Args&&... __args) 120838fd1498Szrj { 120938fd1498Szrj static_assert(_Np < sizeof...(_Types), 121038fd1498Szrj "The index should be in [0, number of alternatives)"); 121138fd1498Szrj this->~variant(); 121238fd1498Szrj __try 121338fd1498Szrj { 121438fd1498Szrj ::new (this) variant(in_place_index<_Np>, __il, 121538fd1498Szrj std::forward<_Args>(__args)...); 121638fd1498Szrj } 121738fd1498Szrj __catch (...) 121838fd1498Szrj { 121938fd1498Szrj this->_M_index = variant_npos; 122038fd1498Szrj __throw_exception_again; 122138fd1498Szrj } 122238fd1498Szrj __glibcxx_assert(index() == _Np); 122338fd1498Szrj return std::get<_Np>(*this); 122438fd1498Szrj } 122538fd1498Szrj 122638fd1498Szrj constexpr bool valueless_by_exception() const noexcept 122738fd1498Szrj { return !this->_M_valid(); } 122838fd1498Szrj 122938fd1498Szrj constexpr size_t index() const noexcept 123038fd1498Szrj { 123138fd1498Szrj if (this->_M_index == 123238fd1498Szrj typename _Base::__index_type(variant_npos)) 123338fd1498Szrj return variant_npos; 123438fd1498Szrj return this->_M_index; 123538fd1498Szrj } 123638fd1498Szrj 123738fd1498Szrj void 123838fd1498Szrj swap(variant& __rhs) 123938fd1498Szrj noexcept((__is_nothrow_swappable<_Types>::value && ...) 124038fd1498Szrj && is_nothrow_move_constructible_v<variant>) 124138fd1498Szrj { 124238fd1498Szrj if (this->index() == __rhs.index()) 124338fd1498Szrj { 124438fd1498Szrj if (this->_M_valid()) 124538fd1498Szrj { 124638fd1498Szrj static constexpr void (*_S_vtable[])(void*, void*) = 124738fd1498Szrj { &__detail::__variant::__erased_swap<_Types&, _Types&>... }; 124838fd1498Szrj _S_vtable[__rhs._M_index](this->_M_storage(), 124938fd1498Szrj __rhs._M_storage()); 125038fd1498Szrj } 125138fd1498Szrj } 125238fd1498Szrj else if (!this->_M_valid()) 125338fd1498Szrj { 125438fd1498Szrj this->_M_destructive_move(std::move(__rhs)); 125538fd1498Szrj __rhs._M_reset(); 125638fd1498Szrj } 125738fd1498Szrj else if (!__rhs._M_valid()) 125838fd1498Szrj { 125938fd1498Szrj __rhs._M_destructive_move(std::move(*this)); 126038fd1498Szrj this->_M_reset(); 126138fd1498Szrj } 126238fd1498Szrj else 126338fd1498Szrj { 126438fd1498Szrj auto __tmp = std::move(__rhs); 126538fd1498Szrj __rhs._M_destructive_move(std::move(*this)); 126638fd1498Szrj this->_M_destructive_move(std::move(__tmp)); 126738fd1498Szrj } 126838fd1498Szrj } 126938fd1498Szrj 127038fd1498Szrj private: 127138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ 127238fd1498Szrj template<size_t... __indices> \ 127338fd1498Szrj static constexpr bool \ 127438fd1498Szrj (*_S_erased_##__NAME[])(const variant&, const variant&) = \ 127538fd1498Szrj { &__detail::__variant::__erased_##__NAME< \ 127638fd1498Szrj const variant&, __indices>... }; \ 127738fd1498Szrj template<size_t... __indices> \ 127838fd1498Szrj constexpr inline bool \ 127938fd1498Szrj _M_##__NAME(const variant& __rhs, \ 128038fd1498Szrj std::index_sequence<__indices...>) const \ 128138fd1498Szrj { \ 128238fd1498Szrj auto __lhs_index = this->index(); \ 128338fd1498Szrj auto __rhs_index = __rhs.index(); \ 128438fd1498Szrj if (__lhs_index != __rhs_index || valueless_by_exception()) \ 128538fd1498Szrj /* Modulo addition. */ \ 128638fd1498Szrj return __lhs_index + 1 __OP __rhs_index + 1; \ 128738fd1498Szrj return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \ 128838fd1498Szrj } 128938fd1498Szrj 129038fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) 129138fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) 129238fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) 129338fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) 129438fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) 129538fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) 129638fd1498Szrj 129738fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 129838fd1498Szrj 129938fd1498Szrj#ifdef __clang__ 130038fd1498Szrj public: 130138fd1498Szrj using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 130238fd1498Szrj private: 130338fd1498Szrj#endif 130438fd1498Szrj 130538fd1498Szrj template<size_t _Np, typename _Vp> 130638fd1498Szrj friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v); 130738fd1498Szrj 130838fd1498Szrj template<typename _Vp> 130938fd1498Szrj friend void* __detail::__variant::__get_storage(_Vp&& __v); 131038fd1498Szrj 131138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ 131238fd1498Szrj template<typename... _Tp> \ 131338fd1498Szrj friend constexpr bool \ 131438fd1498Szrj operator __OP(const variant<_Tp...>& __lhs, \ 131538fd1498Szrj const variant<_Tp...>& __rhs); 131638fd1498Szrj 131738fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<) 131838fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) 131938fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(==) 132038fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) 132138fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) 132238fd1498Szrj _VARIANT_RELATION_FUNCTION_TEMPLATE(>) 132338fd1498Szrj 132438fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE 132538fd1498Szrj }; 132638fd1498Szrj 132738fd1498Szrj template<size_t _Np, typename... _Types> 132838fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>>& 132938fd1498Szrj get(variant<_Types...>& __v) 133038fd1498Szrj { 133138fd1498Szrj static_assert(_Np < sizeof...(_Types), 133238fd1498Szrj "The index should be in [0, number of alternatives)"); 133338fd1498Szrj if (__v.index() != _Np) 133438fd1498Szrj __throw_bad_variant_access("Unexpected index"); 133538fd1498Szrj return __detail::__variant::__get<_Np>(__v); 133638fd1498Szrj } 133738fd1498Szrj 133838fd1498Szrj template<size_t _Np, typename... _Types> 133938fd1498Szrj constexpr variant_alternative_t<_Np, variant<_Types...>>&& 134038fd1498Szrj get(variant<_Types...>&& __v) 134138fd1498Szrj { 134238fd1498Szrj static_assert(_Np < sizeof...(_Types), 134338fd1498Szrj "The index should be in [0, number of alternatives)"); 134438fd1498Szrj if (__v.index() != _Np) 134538fd1498Szrj __throw_bad_variant_access("Unexpected index"); 134638fd1498Szrj return __detail::__variant::__get<_Np>(std::move(__v)); 134738fd1498Szrj } 134838fd1498Szrj 134938fd1498Szrj template<size_t _Np, typename... _Types> 135038fd1498Szrj constexpr const variant_alternative_t<_Np, variant<_Types...>>& 135138fd1498Szrj get(const variant<_Types...>& __v) 135238fd1498Szrj { 135338fd1498Szrj static_assert(_Np < sizeof...(_Types), 135438fd1498Szrj "The index should be in [0, number of alternatives)"); 135538fd1498Szrj if (__v.index() != _Np) 135638fd1498Szrj __throw_bad_variant_access("Unexpected index"); 135738fd1498Szrj return __detail::__variant::__get<_Np>(__v); 135838fd1498Szrj } 135938fd1498Szrj 136038fd1498Szrj template<size_t _Np, typename... _Types> 136138fd1498Szrj constexpr const variant_alternative_t<_Np, variant<_Types...>>&& 136238fd1498Szrj get(const variant<_Types...>&& __v) 136338fd1498Szrj { 136438fd1498Szrj static_assert(_Np < sizeof...(_Types), 136538fd1498Szrj "The index should be in [0, number of alternatives)"); 136638fd1498Szrj if (__v.index() != _Np) 136738fd1498Szrj __throw_bad_variant_access("Unexpected index"); 136838fd1498Szrj return __detail::__variant::__get<_Np>(std::move(__v)); 136938fd1498Szrj } 137038fd1498Szrj 137138fd1498Szrj template<typename _Visitor, typename... _Variants> 137238fd1498Szrj constexpr decltype(auto) 137338fd1498Szrj visit(_Visitor&& __visitor, _Variants&&... __variants) 137438fd1498Szrj { 137538fd1498Szrj if ((__variants.valueless_by_exception() || ...)) 137638fd1498Szrj __throw_bad_variant_access("Unexpected index"); 137738fd1498Szrj 137838fd1498Szrj using _Result_type = 137938fd1498Szrj decltype(std::forward<_Visitor>(__visitor)( 1380*58e805e6Szrj std::get<0>(std::forward<_Variants>(__variants))...)); 138138fd1498Szrj 138238fd1498Szrj constexpr auto& __vtable = __detail::__variant::__gen_vtable< 138338fd1498Szrj _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; 138438fd1498Szrj 138538fd1498Szrj auto __func_ptr = __vtable._M_access(__variants.index()...); 138638fd1498Szrj return (*__func_ptr)(std::forward<_Visitor>(__visitor), 138738fd1498Szrj std::forward<_Variants>(__variants)...); 138838fd1498Szrj } 138938fd1498Szrj 139038fd1498Szrj template<bool, typename... _Types> 139138fd1498Szrj struct __variant_hash_call_base_impl 139238fd1498Szrj { 139338fd1498Szrj size_t 139438fd1498Szrj operator()(const variant<_Types...>& __t) const 139538fd1498Szrj noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...)) 139638fd1498Szrj { 139738fd1498Szrj if (!__t.valueless_by_exception()) 139838fd1498Szrj { 139938fd1498Szrj namespace __edv = __detail::__variant; 140038fd1498Szrj static constexpr size_t (*_S_vtable[])(void*) = 140138fd1498Szrj { &__edv::__erased_hash<const _Types&>... }; 140238fd1498Szrj return hash<size_t>{}(__t.index()) 140338fd1498Szrj + _S_vtable[__t.index()](__edv::__get_storage(__t)); 140438fd1498Szrj } 140538fd1498Szrj return hash<size_t>{}(__t.index()); 140638fd1498Szrj } 140738fd1498Szrj }; 140838fd1498Szrj 140938fd1498Szrj template<typename... _Types> 141038fd1498Szrj struct __variant_hash_call_base_impl<false, _Types...> {}; 141138fd1498Szrj 141238fd1498Szrj template<typename... _Types> 141338fd1498Szrj using __variant_hash_call_base = 141438fd1498Szrj __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>:: 141538fd1498Szrj __enable_hash_call &&...), _Types...>; 141638fd1498Szrj 141738fd1498Szrj template<typename... _Types> 141838fd1498Szrj struct hash<variant<_Types...>> 141938fd1498Szrj : private __detail::__variant::_Variant_hash_base< 142038fd1498Szrj variant<_Types...>, std::index_sequence_for<_Types...>>, 142138fd1498Szrj public __variant_hash_call_base<_Types...> 142238fd1498Szrj { 142338fd1498Szrj using result_type [[__deprecated__]] = size_t; 142438fd1498Szrj using argument_type [[__deprecated__]] = variant<_Types...>; 142538fd1498Szrj }; 142638fd1498Szrj 142738fd1498Szrj template<> 142838fd1498Szrj struct hash<monostate> 142938fd1498Szrj { 143038fd1498Szrj using result_type [[__deprecated__]] = size_t; 143138fd1498Szrj using argument_type [[__deprecated__]] = monostate; 143238fd1498Szrj 143338fd1498Szrj size_t 143438fd1498Szrj operator()(const monostate& __t) const noexcept 143538fd1498Szrj { 143638fd1498Szrj constexpr size_t __magic_monostate_hash = -7777; 143738fd1498Szrj return __magic_monostate_hash; 143838fd1498Szrj } 143938fd1498Szrj }; 144038fd1498Szrj 144138fd1498Szrj template<typename... _Types> 144238fd1498Szrj struct __is_fast_hash<hash<variant<_Types...>>> 144338fd1498Szrj : bool_constant<(__is_fast_hash<_Types>::value && ...)> 144438fd1498Szrj { }; 144538fd1498Szrj 144638fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION 144738fd1498Szrj} // namespace std 144838fd1498Szrj 144938fd1498Szrj#endif // C++17 145038fd1498Szrj 145138fd1498Szrj#endif // _GLIBCXX_VARIANT 1452