| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451 |
- // <variant> -*- C++ -*-
- // Copyright (C) 2016-2018 Free Software Foundation, Inc.
- //
- // This file is part of the GNU ISO C++ Library. This library is free
- // software; you can redistribute it and/or modify it under the
- // terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 3, or (at your option)
- // any later version.
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- // Under Section 7 of GPL version 3, you are granted additional
- // permissions described in the GCC Runtime Library Exception, version
- // 3.1, as published by the Free Software Foundation.
- // You should have received a copy of the GNU General Public License and
- // a copy of the GCC Runtime Library Exception along with this program;
- // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- // <http://www.gnu.org/licenses/>.
- /** @file variant
- * This is the <variant> C++ Library header.
- */
- #ifndef _GLIBCXX_VARIANT
- #define _GLIBCXX_VARIANT 1
- #pragma GCC system_header
- #if __cplusplus >= 201703L
- #include <type_traits>
- #include <utility>
- #include <bits/enable_special_members.h>
- #include <bits/functexcept.h>
- #include <bits/move.h>
- #include <bits/functional_hash.h>
- #include <bits/invoke.h>
- #include <ext/aligned_buffer.h>
- #include <bits/parse_numbers.h>
- #include <bits/stl_iterator_base_types.h>
- #include <bits/stl_iterator_base_funcs.h>
- #include <bits/stl_construct.h>
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- namespace __detail
- {
- namespace __variant
- {
- template<size_t _Np, typename... _Types>
- struct _Nth_type;
- template<size_t _Np, typename _First, typename... _Rest>
- struct _Nth_type<_Np, _First, _Rest...>
- : _Nth_type<_Np-1, _Rest...> { };
- template<typename _First, typename... _Rest>
- struct _Nth_type<0, _First, _Rest...>
- { using type = _First; };
- } // namespace __variant
- } // namespace __detail
- #define __cpp_lib_variant 201603
- template<typename... _Types> class tuple;
- template<typename... _Types> class variant;
- template <typename> struct hash;
- template<typename _Variant>
- struct variant_size;
- template<typename _Variant>
- struct variant_size<const _Variant> : variant_size<_Variant> {};
- template<typename _Variant>
- struct variant_size<volatile _Variant> : variant_size<_Variant> {};
- template<typename _Variant>
- struct variant_size<const volatile _Variant> : variant_size<_Variant> {};
- template<typename... _Types>
- struct variant_size<variant<_Types...>>
- : std::integral_constant<size_t, sizeof...(_Types)> {};
- template<typename _Variant>
- inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
- template<size_t _Np, typename _Variant>
- struct variant_alternative;
- template<size_t _Np, typename _First, typename... _Rest>
- struct variant_alternative<_Np, variant<_First, _Rest...>>
- : variant_alternative<_Np-1, variant<_Rest...>> {};
- template<typename _First, typename... _Rest>
- struct variant_alternative<0, variant<_First, _Rest...>>
- { using type = _First; };
- template<size_t _Np, typename _Variant>
- using variant_alternative_t =
- typename variant_alternative<_Np, _Variant>::type;
- template<size_t _Np, typename _Variant>
- struct variant_alternative<_Np, const _Variant>
- { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; };
- template<size_t _Np, typename _Variant>
- struct variant_alternative<_Np, volatile _Variant>
- { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; };
- template<size_t _Np, typename _Variant>
- struct variant_alternative<_Np, const volatile _Variant>
- { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; };
- inline constexpr size_t variant_npos = -1;
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>>&
- get(variant<_Types...>&);
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>>&&
- get(variant<_Types...>&&);
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>> const&
- get(const variant<_Types...>&);
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
- get(const variant<_Types...>&&);
- namespace __detail
- {
- namespace __variant
- {
- // Returns the first apparence of _Tp in _Types.
- // Returns sizeof...(_Types) if _Tp is not in _Types.
- template<typename _Tp, typename... _Types>
- struct __index_of : std::integral_constant<size_t, 0> {};
- template<typename _Tp, typename... _Types>
- inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value;
- template<typename _Tp, typename _First, typename... _Rest>
- struct __index_of<_Tp, _First, _Rest...> :
- std::integral_constant<size_t, is_same_v<_Tp, _First>
- ? 0 : __index_of_v<_Tp, _Rest...> + 1> {};
- // _Uninitialized<T> is guaranteed to be a literal type, even if T is not.
- // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented
- // yet. When it's implemented, _Uninitialized<T> can be changed to the alias
- // to T, therefore equivalent to being removed entirely.
- //
- // Another reason we may not want to remove _Uninitialzied<T> may be that, we
- // want _Uninitialized<T> to be trivially destructible, no matter whether T
- // is; but we will see.
- template<typename _Type, bool = std::is_literal_type_v<_Type>>
- struct _Uninitialized;
- template<typename _Type>
- struct _Uninitialized<_Type, true>
- {
- template<typename... _Args>
- constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
- : _M_storage(std::forward<_Args>(__args)...)
- { }
- constexpr const _Type& _M_get() const &
- { return _M_storage; }
- constexpr _Type& _M_get() &
- { return _M_storage; }
- constexpr const _Type&& _M_get() const &&
- { return std::move(_M_storage); }
- constexpr _Type&& _M_get() &&
- { return std::move(_M_storage); }
- _Type _M_storage;
- };
- template<typename _Type>
- struct _Uninitialized<_Type, false>
- {
- template<typename... _Args>
- constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
- { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); }
- const _Type& _M_get() const &
- { return *_M_storage._M_ptr(); }
- _Type& _M_get() &
- { return *_M_storage._M_ptr(); }
- const _Type&& _M_get() const &&
- { return std::move(*_M_storage._M_ptr()); }
- _Type&& _M_get() &&
- { return std::move(*_M_storage._M_ptr()); }
- __gnu_cxx::__aligned_membuf<_Type> _M_storage;
- };
- template<typename _Ref>
- _Ref __ref_cast(void* __ptr)
- {
- return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr));
- }
- template<typename _Union>
- constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u)
- { return std::forward<_Union>(__u)._M_first._M_get(); }
- template<size_t _Np, typename _Union>
- constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u)
- {
- return __variant::__get(in_place_index<_Np-1>,
- std::forward<_Union>(__u)._M_rest);
- }
- // Returns the typed storage for __v.
- template<size_t _Np, typename _Variant>
- constexpr decltype(auto) __get(_Variant&& __v)
- {
- return __variant::__get(std::in_place_index<_Np>,
- std::forward<_Variant>(__v)._M_u);
- }
- // Various functions as "vtable" entries, where those vtables are used by
- // polymorphic operations.
- template<typename _Lhs, typename _Rhs>
- void
- __erased_ctor(void* __lhs, void* __rhs)
- {
- using _Type = remove_reference_t<_Lhs>;
- ::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs));
- }
- template<typename _Variant, size_t _Np>
- void
- __erased_dtor(_Variant&& __v)
- { std::_Destroy(std::__addressof(__variant::__get<_Np>(__v))); }
- template<typename _Lhs, typename _Rhs>
- void
- __erased_assign(void* __lhs, void* __rhs)
- {
- __variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs);
- }
- template<typename _Lhs, typename _Rhs>
- void
- __erased_swap(void* __lhs, void* __rhs)
- {
- using std::swap;
- swap(__variant::__ref_cast<_Lhs>(__lhs),
- __variant::__ref_cast<_Rhs>(__rhs));
- }
- #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
- template<typename _Variant, size_t _Np> \
- constexpr bool \
- __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \
- { \
- return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \
- __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \
- }
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
- #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
- template<typename _Tp>
- size_t
- __erased_hash(void* __t)
- {
- return std::hash<remove_cv_t<remove_reference_t<_Tp>>>{}(
- __variant::__ref_cast<_Tp>(__t));
- }
- template<typename... _Types>
- struct _Traits
- {
- static constexpr bool _S_default_ctor =
- is_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
- static constexpr bool _S_copy_ctor =
- (is_copy_constructible_v<_Types> && ...);
- static constexpr bool _S_move_ctor =
- (is_move_constructible_v<_Types> && ...);
- static constexpr bool _S_copy_assign =
- _S_copy_ctor && _S_move_ctor
- && (is_copy_assignable_v<_Types> && ...);
- static constexpr bool _S_move_assign =
- _S_move_ctor
- && (is_move_assignable_v<_Types> && ...);
- static constexpr bool _S_trivial_dtor =
- (is_trivially_destructible_v<_Types> && ...);
- static constexpr bool _S_trivial_copy_ctor =
- (is_trivially_copy_constructible_v<_Types> && ...);
- static constexpr bool _S_trivial_move_ctor =
- (is_trivially_move_constructible_v<_Types> && ...);
- static constexpr bool _S_trivial_copy_assign =
- _S_trivial_dtor && (is_trivially_copy_assignable_v<_Types> && ...);
- static constexpr bool _S_trivial_move_assign =
- _S_trivial_dtor && (is_trivially_move_assignable_v<_Types> && ...);
- // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
- // are always nothrow.
- static constexpr bool _S_nothrow_default_ctor =
- is_nothrow_default_constructible_v<
- typename _Nth_type<0, _Types...>::type>;
- static constexpr bool _S_nothrow_copy_ctor = false;
- static constexpr bool _S_nothrow_move_ctor =
- (is_nothrow_move_constructible_v<_Types> && ...);
- static constexpr bool _S_nothrow_copy_assign = false;
- static constexpr bool _S_nothrow_move_assign =
- _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...);
- };
- // Defines members and ctors.
- template<typename... _Types>
- union _Variadic_union { };
- template<typename _First, typename... _Rest>
- union _Variadic_union<_First, _Rest...>
- {
- constexpr _Variadic_union() : _M_rest() { }
- template<typename... _Args>
- constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args)
- : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
- { }
- template<size_t _Np, typename... _Args>
- constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
- : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
- { }
- _Uninitialized<_First> _M_first;
- _Variadic_union<_Rest...> _M_rest;
- };
- // Defines index and the dtor, possibly trivial.
- template<bool __trivially_destructible, typename... _Types>
- struct _Variant_storage;
- template <typename... _Types>
- using __select_index =
- typename __select_int::_Select_int_base<sizeof...(_Types) + 1,
- unsigned char,
- unsigned short>::type::value_type;
- template<typename... _Types>
- struct _Variant_storage<false, _Types...>
- {
- template<size_t... __indices>
- static constexpr void (*_S_vtable[])(const _Variant_storage&) =
- { &__erased_dtor<const _Variant_storage&, __indices>... };
- constexpr _Variant_storage() : _M_index(variant_npos) { }
- template<size_t _Np, typename... _Args>
- constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
- : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
- _M_index(_Np)
- { }
- template<size_t... __indices>
- constexpr void _M_reset_impl(std::index_sequence<__indices...>)
- {
- if (_M_index != __index_type(variant_npos))
- _S_vtable<__indices...>[_M_index](*this);
- }
- void _M_reset()
- {
- _M_reset_impl(std::index_sequence_for<_Types...>{});
- _M_index = variant_npos;
- }
- ~_Variant_storage()
- { _M_reset(); }
- void*
- _M_storage() const
- {
- return const_cast<void*>(static_cast<const void*>(
- std::addressof(_M_u)));
- }
- constexpr bool
- _M_valid() const noexcept
- {
- return this->_M_index != __index_type(variant_npos);
- }
- _Variadic_union<_Types...> _M_u;
- using __index_type = __select_index<_Types...>;
- __index_type _M_index;
- };
- template<typename... _Types>
- struct _Variant_storage<true, _Types...>
- {
- constexpr _Variant_storage() : _M_index(variant_npos) { }
- template<size_t _Np, typename... _Args>
- constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
- : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
- _M_index(_Np)
- { }
- void _M_reset()
- { _M_index = variant_npos; }
- void*
- _M_storage() const
- {
- return const_cast<void*>(static_cast<const void*>(
- std::addressof(_M_u)));
- }
- constexpr bool
- _M_valid() const noexcept
- {
- return this->_M_index != __index_type(variant_npos);
- }
- _Variadic_union<_Types...> _M_u;
- using __index_type = __select_index<_Types...>;
- __index_type _M_index;
- };
- template<typename... _Types>
- using _Variant_storage_alias =
- _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
- // The following are (Copy|Move) (ctor|assign) layers for forwarding
- // triviality and handling non-trivial SMF behaviors.
- template<bool, typename... _Types>
- struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
- {
- using _Base = _Variant_storage_alias<_Types...>;
- using _Base::_Base;
- _Copy_ctor_base(const _Copy_ctor_base& __rhs)
- noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
- {
- if (__rhs._M_valid())
- {
- static constexpr void (*_S_vtable[])(void*, void*) =
- { &__erased_ctor<_Types&, const _Types&>... };
- _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
- this->_M_index = __rhs._M_index;
- }
- }
- _Copy_ctor_base(_Copy_ctor_base&&) = default;
- _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default;
- _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default;
- };
- template<typename... _Types>
- struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...>
- {
- using _Base = _Variant_storage_alias<_Types...>;
- using _Base::_Base;
- };
- template<typename... _Types>
- using _Copy_ctor_alias =
- _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>;
- template<bool, typename... _Types>
- struct _Move_ctor_base : _Copy_ctor_alias<_Types...>
- {
- using _Base = _Copy_ctor_alias<_Types...>;
- using _Base::_Base;
- _Move_ctor_base(_Move_ctor_base&& __rhs)
- noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
- {
- if (__rhs._M_valid())
- {
- static constexpr void (*_S_vtable[])(void*, void*) =
- { &__erased_ctor<_Types&, _Types&&>... };
- _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
- this->_M_index = __rhs._M_index;
- }
- }
- void _M_destructive_move(_Move_ctor_base&& __rhs)
- {
- this->~_Move_ctor_base();
- __try
- {
- ::new (this) _Move_ctor_base(std::move(__rhs));
- }
- __catch (...)
- {
- this->_M_index = variant_npos;
- __throw_exception_again;
- }
- }
- _Move_ctor_base(const _Move_ctor_base&) = default;
- _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
- _Move_ctor_base& operator=(_Move_ctor_base&&) = default;
- };
- template<typename... _Types>
- struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...>
- {
- using _Base = _Copy_ctor_alias<_Types...>;
- using _Base::_Base;
- void _M_destructive_move(_Move_ctor_base&& __rhs)
- {
- this->~_Move_ctor_base();
- ::new (this) _Move_ctor_base(std::move(__rhs));
- }
- };
- template<typename... _Types>
- using _Move_ctor_alias =
- _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>;
- template<bool, typename... _Types>
- struct _Copy_assign_base : _Move_ctor_alias<_Types...>
- {
- using _Base = _Move_ctor_alias<_Types...>;
- using _Base::_Base;
- _Copy_assign_base&
- operator=(const _Copy_assign_base& __rhs)
- noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
- {
- if (this->_M_index == __rhs._M_index)
- {
- if (__rhs._M_valid())
- {
- static constexpr void (*_S_vtable[])(void*, void*) =
- { &__erased_assign<_Types&, const _Types&>... };
- _S_vtable[__rhs._M_index](this->_M_storage(),
- __rhs._M_storage());
- }
- }
- else
- {
- _Copy_assign_base __tmp(__rhs);
- this->_M_destructive_move(std::move(__tmp));
- }
- __glibcxx_assert(this->_M_index == __rhs._M_index);
- return *this;
- }
- _Copy_assign_base(const _Copy_assign_base&) = default;
- _Copy_assign_base(_Copy_assign_base&&) = default;
- _Copy_assign_base& operator=(_Copy_assign_base&&) = default;
- };
- template<typename... _Types>
- struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...>
- {
- using _Base = _Move_ctor_alias<_Types...>;
- using _Base::_Base;
- };
- template<typename... _Types>
- using _Copy_assign_alias =
- _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign,
- _Types...>;
- template<bool, typename... _Types>
- struct _Move_assign_base : _Copy_assign_alias<_Types...>
- {
- using _Base = _Copy_assign_alias<_Types...>;
- using _Base::_Base;
- _Move_assign_base&
- operator=(_Move_assign_base&& __rhs)
- noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
- {
- if (this->_M_index == __rhs._M_index)
- {
- if (__rhs._M_valid())
- {
- static constexpr void (*_S_vtable[])(void*, void*) =
- { &__erased_assign<_Types&, _Types&&>... };
- _S_vtable[__rhs._M_index]
- (this->_M_storage(), __rhs._M_storage());
- }
- }
- else
- {
- _Move_assign_base __tmp(std::move(__rhs));
- this->_M_destructive_move(std::move(__tmp));
- }
- __glibcxx_assert(this->_M_index == __rhs._M_index);
- return *this;
- }
- _Move_assign_base(const _Move_assign_base&) = default;
- _Move_assign_base(_Move_assign_base&&) = default;
- _Move_assign_base& operator=(const _Move_assign_base&) = default;
- };
- template<typename... _Types>
- struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...>
- {
- using _Base = _Copy_assign_alias<_Types...>;
- using _Base::_Base;
- };
- template<typename... _Types>
- using _Move_assign_alias =
- _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign,
- _Types...>;
- template<typename... _Types>
- struct _Variant_base : _Move_assign_alias<_Types...>
- {
- using _Base = _Move_assign_alias<_Types...>;
- constexpr
- _Variant_base()
- noexcept(_Traits<_Types...>::_S_nothrow_default_ctor)
- : _Variant_base(in_place_index<0>) { }
- template<size_t _Np, typename... _Args>
- constexpr explicit
- _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
- : _Base(__i, std::forward<_Args>(__args)...)
- { }
- _Variant_base(const _Variant_base&) = default;
- _Variant_base(_Variant_base&&) = default;
- _Variant_base& operator=(const _Variant_base&) = default;
- _Variant_base& operator=(_Variant_base&&) = default;
- };
- // For how many times does _Tp appear in _Tuple?
- template<typename _Tp, typename _Tuple>
- struct __tuple_count;
- template<typename _Tp, typename _Tuple>
- inline constexpr size_t __tuple_count_v =
- __tuple_count<_Tp, _Tuple>::value;
- template<typename _Tp, typename... _Types>
- struct __tuple_count<_Tp, tuple<_Types...>>
- : integral_constant<size_t, 0> { };
- template<typename _Tp, typename _First, typename... _Rest>
- struct __tuple_count<_Tp, tuple<_First, _Rest...>>
- : integral_constant<
- size_t,
- __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { };
- // TODO: Reuse this in <tuple> ?
- template<typename _Tp, typename... _Types>
- inline constexpr bool __exactly_once =
- __tuple_count_v<_Tp, tuple<_Types...>> == 1;
- // Takes _Types and create an overloaded _S_fun for each type.
- // If a type appears more than once in _Types, create only one overload.
- template<typename... _Types>
- struct __overload_set
- { static void _S_fun(); };
- template<typename _First, typename... _Rest>
- struct __overload_set<_First, _Rest...> : __overload_set<_Rest...>
- {
- using __overload_set<_Rest...>::_S_fun;
- static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
- };
- template<typename... _Rest>
- struct __overload_set<void, _Rest...> : __overload_set<_Rest...>
- {
- using __overload_set<_Rest...>::_S_fun;
- };
- // Helper for variant(_Tp&&) and variant::operator=(_Tp&&).
- // __accepted_index maps the arbitrary _Tp to an alternative type in _Variant.
- template<typename _Tp, typename _Variant, typename = void>
- struct __accepted_index
- { static constexpr size_t value = variant_npos; };
- template<typename _Tp, typename... _Types>
- struct __accepted_index<
- _Tp, variant<_Types...>,
- decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
- std::declval<void>())>
- {
- static constexpr size_t value = sizeof...(_Types) - 1
- - decltype(__overload_set<_Types...>::
- _S_fun(std::declval<_Tp>()))::value;
- };
- // Returns the raw storage for __v.
- template<typename _Variant>
- void* __get_storage(_Variant&& __v)
- { return __v._M_storage(); }
- // Used for storing multi-dimensional vtable.
- template<typename _Tp, size_t... _Dimensions>
- struct _Multi_array
- {
- constexpr const _Tp&
- _M_access() const
- { return _M_data; }
- _Tp _M_data;
- };
- template<typename _Tp, size_t __first, size_t... __rest>
- struct _Multi_array<_Tp, __first, __rest...>
- {
- template<typename... _Args>
- constexpr const _Tp&
- _M_access(size_t __first_index, _Args... __rest_indices) const
- { return _M_arr[__first_index]._M_access(__rest_indices...); }
- _Multi_array<_Tp, __rest...> _M_arr[__first];
- };
- // Creates a multi-dimensional vtable recursively.
- //
- // For example,
- // visit([](auto, auto){},
- // variant<int, char>(), // typedef'ed as V1
- // variant<float, double, long double>()) // typedef'ed as V2
- // will trigger instantiations of:
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>,
- // tuple<V1&&, V2&&>, std::index_sequence<>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
- // tuple<V1&&, V2&&>, std::index_sequence<0>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<0, 0>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<0, 1>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<0, 2>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
- // tuple<V1&&, V2&&>, std::index_sequence<1>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<1, 0>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<1, 1>>
- // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
- // tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
- // The returned multi-dimensional vtable can be fast accessed by the visitor
- // using index calculation.
- template<typename _Array_type, typename _Variant_tuple, typename _Index_seq>
- struct __gen_vtable_impl;
- template<typename _Result_type, typename _Visitor, size_t... __dimensions,
- typename... _Variants, size_t... __indices>
- struct __gen_vtable_impl<
- _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
- tuple<_Variants...>, std::index_sequence<__indices...>>
- {
- using _Next =
- remove_reference_t<typename _Nth_type<sizeof...(__indices),
- _Variants...>::type>;
- using _Array_type =
- _Multi_array<_Result_type (*)(_Visitor, _Variants...),
- __dimensions...>;
- static constexpr _Array_type
- _S_apply()
- {
- _Array_type __vtable{};
- _S_apply_all_alts(
- __vtable, make_index_sequence<variant_size_v<_Next>>());
- return __vtable;
- }
- template<size_t... __var_indices>
- static constexpr void
- _S_apply_all_alts(_Array_type& __vtable,
- std::index_sequence<__var_indices...>)
- {
- (_S_apply_single_alt<__var_indices>(
- __vtable._M_arr[__var_indices]), ...);
- }
- template<size_t __index, typename _Tp>
- static constexpr void
- _S_apply_single_alt(_Tp& __element)
- {
- using _Alternative = variant_alternative_t<__index, _Next>;
- __element = __gen_vtable_impl<
- remove_reference_t<
- decltype(__element)>, tuple<_Variants...>,
- std::index_sequence<__indices..., __index>>::_S_apply();
- }
- };
- template<typename _Result_type, typename _Visitor, typename... _Variants,
- size_t... __indices>
- struct __gen_vtable_impl<
- _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
- tuple<_Variants...>, std::index_sequence<__indices...>>
- {
- using _Array_type =
- _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>;
- decltype(auto)
- static constexpr __visit_invoke(_Visitor&& __visitor, _Variants... __vars)
- {
- return std::__invoke(std::forward<_Visitor>(__visitor),
- std::get<__indices>(std::forward<_Variants>(__vars))...);
- }
- static constexpr auto
- _S_apply()
- { return _Array_type{&__visit_invoke}; }
- };
- template<typename _Result_type, typename _Visitor, typename... _Variants>
- struct __gen_vtable
- {
- using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...);
- using _Array_type =
- _Multi_array<_Func_ptr,
- variant_size_v<remove_reference_t<_Variants>>...>;
- static constexpr _Array_type
- _S_apply()
- {
- return __gen_vtable_impl<_Array_type, tuple<_Variants...>,
- std::index_sequence<>>::_S_apply();
- }
- static constexpr auto _S_vtable = _S_apply();
- };
- template<size_t _Np, typename _Tp>
- struct _Base_dedup : public _Tp { };
- template<typename _Variant, typename __indices>
- struct _Variant_hash_base;
- template<typename... _Types, size_t... __indices>
- struct _Variant_hash_base<variant<_Types...>,
- std::index_sequence<__indices...>>
- : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
- } // namespace __variant
- } // namespace __detail
- template<typename _Tp, typename... _Types>
- inline constexpr bool holds_alternative(const variant<_Types...>& __v)
- noexcept
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>;
- }
- template<typename _Tp, typename... _Types>
- constexpr inline _Tp& get(variant<_Types...>& __v)
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
- }
- template<typename _Tp, typename... _Types>
- constexpr inline _Tp&& get(variant<_Types...>&& __v)
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
- std::move(__v));
- }
- template<typename _Tp, typename... _Types>
- constexpr inline const _Tp& get(const variant<_Types...>& __v)
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
- }
- template<typename _Tp, typename... _Types>
- constexpr inline const _Tp&& get(const variant<_Types...>&& __v)
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
- std::move(__v));
- }
- template<size_t _Np, typename... _Types>
- constexpr inline
- add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>>
- get_if(variant<_Types...>* __ptr) noexcept
- {
- using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
- if (__ptr && __ptr->index() == _Np)
- return &__detail::__variant::__get<_Np>(*__ptr);
- return nullptr;
- }
- template<size_t _Np, typename... _Types>
- constexpr inline
- add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>>
- get_if(const variant<_Types...>* __ptr) noexcept
- {
- using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
- if (__ptr && __ptr->index() == _Np)
- return &__detail::__variant::__get<_Np>(*__ptr);
- return nullptr;
- }
- template<typename _Tp, typename... _Types>
- constexpr inline add_pointer_t<_Tp>
- get_if(variant<_Types...>* __ptr) noexcept
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
- __ptr);
- }
- template<typename _Tp, typename... _Types>
- constexpr inline add_pointer_t<const _Tp>
- get_if(const variant<_Types...>* __ptr)
- noexcept
- {
- static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
- "T should occur for exactly once in alternatives");
- static_assert(!is_void_v<_Tp>, "_Tp should not be void");
- return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
- __ptr);
- }
- struct monostate { };
- #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
- template<typename... _Types> \
- constexpr bool operator __OP(const variant<_Types...>& __lhs, \
- const variant<_Types...>& __rhs) \
- { \
- return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \
- } \
- \
- constexpr bool operator __OP(monostate, monostate) noexcept \
- { return 0 __OP 0; }
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
- #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
- template<typename _Visitor, typename... _Variants>
- constexpr decltype(auto) visit(_Visitor&&, _Variants&&...);
- template<typename... _Types>
- inline enable_if_t<(is_move_constructible_v<_Types> && ...)
- && (is_swappable_v<_Types> && ...)>
- swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
- noexcept(noexcept(__lhs.swap(__rhs)))
- { __lhs.swap(__rhs); }
- template<typename... _Types>
- enable_if_t<!((is_move_constructible_v<_Types> && ...)
- && (is_swappable_v<_Types> && ...))>
- swap(variant<_Types...>&, variant<_Types...>&) = delete;
- class bad_variant_access : public exception
- {
- public:
- bad_variant_access() noexcept : _M_reason("Unknown reason") { }
- const char* what() const noexcept override
- { return _M_reason; }
- private:
- bad_variant_access(const char* __reason) : _M_reason(__reason) { }
- const char* _M_reason;
- friend void __throw_bad_variant_access(const char* __what);
- };
- inline void
- __throw_bad_variant_access(const char* __what)
- { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
- template<typename... _Types>
- class variant
- : private __detail::__variant::_Variant_base<_Types...>,
- private _Enable_default_constructor<
- __detail::__variant::_Traits<_Types...>::_S_default_ctor,
- variant<_Types...>>,
- private _Enable_copy_move<
- __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
- __detail::__variant::_Traits<_Types...>::_S_copy_assign,
- __detail::__variant::_Traits<_Types...>::_S_move_ctor,
- __detail::__variant::_Traits<_Types...>::_S_move_assign,
- variant<_Types...>>
- {
- private:
- static_assert(sizeof...(_Types) > 0,
- "variant must have at least one alternative");
- static_assert(!(std::is_reference_v<_Types> || ...),
- "variant must have no reference alternative");
- static_assert(!(std::is_void_v<_Types> || ...),
- "variant must have no void alternative");
- using _Base = __detail::__variant::_Variant_base<_Types...>;
- using _Default_ctor_enabler =
- _Enable_default_constructor<
- __detail::__variant::_Traits<_Types...>::_S_default_ctor,
- variant<_Types...>>;
- template<typename _Tp>
- static constexpr bool
- __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
- template<typename _Tp>
- static constexpr size_t __accepted_index =
- __detail::__variant::__accepted_index<_Tp&&, variant>::value;
- template<size_t _Np, bool = _Np < sizeof...(_Types)>
- struct __to_type_impl;
- template<size_t _Np>
- struct __to_type_impl<_Np, true>
- { using type = variant_alternative_t<_Np, variant>; };
- template<size_t _Np>
- using __to_type = typename __to_type_impl<_Np>::type;
- template<typename _Tp>
- using __accepted_type = __to_type<__accepted_index<_Tp>>;
- template<typename _Tp>
- static constexpr size_t __index_of =
- __detail::__variant::__index_of_v<_Tp, _Types...>;
- using _Traits = __detail::__variant::_Traits<_Types...>;
- public:
- variant() = default;
- variant(const variant& __rhs) = default;
- variant(variant&&) = default;
- variant& operator=(const variant&) = default;
- variant& operator=(variant&&) = default;
- ~variant() = default;
- template<typename _Tp,
- typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
- typename = enable_if_t<(sizeof...(_Types)>0)>,
- typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
- && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
- constexpr
- variant(_Tp&& __t)
- noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
- : variant(in_place_index<__accepted_index<_Tp&&>>,
- std::forward<_Tp>(__t))
- { __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
- template<typename _Tp, typename... _Args,
- typename = enable_if_t<__exactly_once<_Tp>
- && is_constructible_v<_Tp, _Args&&...>>>
- constexpr explicit
- variant(in_place_type_t<_Tp>, _Args&&... __args)
- : variant(in_place_index<__index_of<_Tp>>,
- std::forward<_Args>(__args)...)
- { __glibcxx_assert(holds_alternative<_Tp>(*this)); }
- template<typename _Tp, typename _Up, typename... _Args,
- typename = enable_if_t<__exactly_once<_Tp>
- && is_constructible_v<
- _Tp, initializer_list<_Up>&, _Args&&...>>>
- constexpr explicit
- variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
- _Args&&... __args)
- : variant(in_place_index<__index_of<_Tp>>, __il,
- std::forward<_Args>(__args)...)
- { __glibcxx_assert(holds_alternative<_Tp>(*this)); }
- template<size_t _Np, typename... _Args,
- typename = enable_if_t<
- is_constructible_v<__to_type<_Np>, _Args&&...>>>
- constexpr explicit
- variant(in_place_index_t<_Np>, _Args&&... __args)
- : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
- _Default_ctor_enabler(_Enable_default_constructor_tag{})
- { __glibcxx_assert(index() == _Np); }
- template<size_t _Np, typename _Up, typename... _Args,
- typename = enable_if_t<is_constructible_v<__to_type<_Np>,
- initializer_list<_Up>&, _Args&&...>>>
- constexpr explicit
- variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
- _Args&&... __args)
- : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
- _Default_ctor_enabler(_Enable_default_constructor_tag{})
- { __glibcxx_assert(index() == _Np); }
- template<typename _Tp>
- enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
- && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
- && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
- && !is_same_v<decay_t<_Tp>, variant>, variant&>
- operator=(_Tp&& __rhs)
- noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
- && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
- {
- constexpr auto __index = __accepted_index<_Tp&&>;
- if (index() == __index)
- std::get<__index>(*this) = std::forward<_Tp>(__rhs);
- else
- this->emplace<__index>(std::forward<_Tp>(__rhs));
- __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this));
- return *this;
- }
- template<typename _Tp, typename... _Args>
- enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
- _Tp&>
- emplace(_Args&&... __args)
- {
- auto& ret =
- this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
- __glibcxx_assert(holds_alternative<_Tp>(*this));
- return ret;
- }
- template<typename _Tp, typename _Up, typename... _Args>
- enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
- && __exactly_once<_Tp>,
- _Tp&>
- emplace(initializer_list<_Up> __il, _Args&&... __args)
- {
- auto& ret =
- this->emplace<__index_of<_Tp>>(__il,
- std::forward<_Args>(__args)...);
- __glibcxx_assert(holds_alternative<_Tp>(*this));
- return ret;
- }
- template<size_t _Np, typename... _Args>
- enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
- _Args...>,
- variant_alternative_t<_Np, variant>&>
- emplace(_Args&&... __args)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- this->~variant();
- __try
- {
- ::new (this) variant(in_place_index<_Np>,
- std::forward<_Args>(__args)...);
- }
- __catch (...)
- {
- this->_M_index = variant_npos;
- __throw_exception_again;
- }
- __glibcxx_assert(index() == _Np);
- return std::get<_Np>(*this);
- }
- template<size_t _Np, typename _Up, typename... _Args>
- enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
- initializer_list<_Up>&, _Args...>,
- variant_alternative_t<_Np, variant>&>
- emplace(initializer_list<_Up> __il, _Args&&... __args)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- this->~variant();
- __try
- {
- ::new (this) variant(in_place_index<_Np>, __il,
- std::forward<_Args>(__args)...);
- }
- __catch (...)
- {
- this->_M_index = variant_npos;
- __throw_exception_again;
- }
- __glibcxx_assert(index() == _Np);
- return std::get<_Np>(*this);
- }
- constexpr bool valueless_by_exception() const noexcept
- { return !this->_M_valid(); }
- constexpr size_t index() const noexcept
- {
- if (this->_M_index ==
- typename _Base::__index_type(variant_npos))
- return variant_npos;
- return this->_M_index;
- }
- void
- swap(variant& __rhs)
- noexcept((__is_nothrow_swappable<_Types>::value && ...)
- && is_nothrow_move_constructible_v<variant>)
- {
- if (this->index() == __rhs.index())
- {
- if (this->_M_valid())
- {
- static constexpr void (*_S_vtable[])(void*, void*) =
- { &__detail::__variant::__erased_swap<_Types&, _Types&>... };
- _S_vtable[__rhs._M_index](this->_M_storage(),
- __rhs._M_storage());
- }
- }
- else if (!this->_M_valid())
- {
- this->_M_destructive_move(std::move(__rhs));
- __rhs._M_reset();
- }
- else if (!__rhs._M_valid())
- {
- __rhs._M_destructive_move(std::move(*this));
- this->_M_reset();
- }
- else
- {
- auto __tmp = std::move(__rhs);
- __rhs._M_destructive_move(std::move(*this));
- this->_M_destructive_move(std::move(__tmp));
- }
- }
- private:
- #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
- template<size_t... __indices> \
- static constexpr bool \
- (*_S_erased_##__NAME[])(const variant&, const variant&) = \
- { &__detail::__variant::__erased_##__NAME< \
- const variant&, __indices>... }; \
- template<size_t... __indices> \
- constexpr inline bool \
- _M_##__NAME(const variant& __rhs, \
- std::index_sequence<__indices...>) const \
- { \
- auto __lhs_index = this->index(); \
- auto __rhs_index = __rhs.index(); \
- if (__lhs_index != __rhs_index || valueless_by_exception()) \
- /* Modulo addition. */ \
- return __lhs_index + 1 __OP __rhs_index + 1; \
- return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \
- }
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
- #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
- #ifdef __clang__
- public:
- using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852
- private:
- #endif
- template<size_t _Np, typename _Vp>
- friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v);
- template<typename _Vp>
- friend void* __detail::__variant::__get_storage(_Vp&& __v);
- #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
- template<typename... _Tp> \
- friend constexpr bool \
- operator __OP(const variant<_Tp...>& __lhs, \
- const variant<_Tp...>& __rhs);
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
- _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
- #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
- };
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>>&
- get(variant<_Types...>& __v)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- if (__v.index() != _Np)
- __throw_bad_variant_access("Unexpected index");
- return __detail::__variant::__get<_Np>(__v);
- }
- template<size_t _Np, typename... _Types>
- constexpr variant_alternative_t<_Np, variant<_Types...>>&&
- get(variant<_Types...>&& __v)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- if (__v.index() != _Np)
- __throw_bad_variant_access("Unexpected index");
- return __detail::__variant::__get<_Np>(std::move(__v));
- }
- template<size_t _Np, typename... _Types>
- constexpr const variant_alternative_t<_Np, variant<_Types...>>&
- get(const variant<_Types...>& __v)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- if (__v.index() != _Np)
- __throw_bad_variant_access("Unexpected index");
- return __detail::__variant::__get<_Np>(__v);
- }
- template<size_t _Np, typename... _Types>
- constexpr const variant_alternative_t<_Np, variant<_Types...>>&&
- get(const variant<_Types...>&& __v)
- {
- static_assert(_Np < sizeof...(_Types),
- "The index should be in [0, number of alternatives)");
- if (__v.index() != _Np)
- __throw_bad_variant_access("Unexpected index");
- return __detail::__variant::__get<_Np>(std::move(__v));
- }
- template<typename _Visitor, typename... _Variants>
- constexpr decltype(auto)
- visit(_Visitor&& __visitor, _Variants&&... __variants)
- {
- if ((__variants.valueless_by_exception() || ...))
- __throw_bad_variant_access("Unexpected index");
- using _Result_type =
- decltype(std::forward<_Visitor>(__visitor)(
- std::get<0>(std::forward<_Variants>(__variants))...));
- constexpr auto& __vtable = __detail::__variant::__gen_vtable<
- _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
- auto __func_ptr = __vtable._M_access(__variants.index()...);
- return (*__func_ptr)(std::forward<_Visitor>(__visitor),
- std::forward<_Variants>(__variants)...);
- }
- template<bool, typename... _Types>
- struct __variant_hash_call_base_impl
- {
- size_t
- operator()(const variant<_Types...>& __t) const
- noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
- {
- if (!__t.valueless_by_exception())
- {
- namespace __edv = __detail::__variant;
- static constexpr size_t (*_S_vtable[])(void*) =
- { &__edv::__erased_hash<const _Types&>... };
- return hash<size_t>{}(__t.index())
- + _S_vtable[__t.index()](__edv::__get_storage(__t));
- }
- return hash<size_t>{}(__t.index());
- }
- };
- template<typename... _Types>
- struct __variant_hash_call_base_impl<false, _Types...> {};
- template<typename... _Types>
- using __variant_hash_call_base =
- __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>::
- __enable_hash_call &&...), _Types...>;
- template<typename... _Types>
- struct hash<variant<_Types...>>
- : private __detail::__variant::_Variant_hash_base<
- variant<_Types...>, std::index_sequence_for<_Types...>>,
- public __variant_hash_call_base<_Types...>
- {
- using result_type [[__deprecated__]] = size_t;
- using argument_type [[__deprecated__]] = variant<_Types...>;
- };
- template<>
- struct hash<monostate>
- {
- using result_type [[__deprecated__]] = size_t;
- using argument_type [[__deprecated__]] = monostate;
- size_t
- operator()(const monostate& __t) const noexcept
- {
- constexpr size_t __magic_monostate_hash = -7777;
- return __magic_monostate_hash;
- }
- };
- template<typename... _Types>
- struct __is_fast_hash<hash<variant<_Types...>>>
- : bool_constant<(__is_fast_hash<_Types>::value && ...)>
- { };
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- #endif // C++17
- #endif // _GLIBCXX_VARIANT
|