| // Copyright (c) 2015, Just Software Solutions Ltd |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or |
| // without modification, are permitted provided that the |
| // following conditions are met: |
| // |
| // 1. Redistributions of source code must retain the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer. |
| // |
| // 2. Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials |
| // provided with the distribution. |
| // |
| // 3. Neither the name of the copyright holder nor the names of |
| // its contributors may be used to endorse or promote products |
| // derived from this software without specific prior written |
| // permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
| // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // Copied from https://bitbucket.org/anthonyw/variant/src (5bce47fa788648f79e5ea1d77b0eef2e8f0b2999) |
| |
| // Modified to make it compile with exceptions disabled. |
| |
| #pragma once |
| |
| #include <functional> |
| #include <limits.h> |
| #include <new> |
| #include <stddef.h> |
| #include <stdexcept> |
| #include <string> |
| #include <type_traits> |
| #include <utility> |
| #include <wtf/Compiler.h> |
| #include <wtf/StdLibExtras.h> |
| |
| #if COMPILER(MSVC) |
| #pragma warning(push) |
| #pragma warning(disable:4245) |
| #pragma warning(disable:4521) |
| #pragma warning(disable:4522) |
| #pragma warning(disable:4814) |
| #endif |
| |
| #if !COMPILER(CLANG) || WTF_CPP_STD_VER >= 14 |
| |
| namespace WTF { |
| |
| #if COMPILER_SUPPORTS(EXCEPTIONS) |
| #define __THROW_EXCEPTION(__exception) throw __exception; |
| #define __NOEXCEPT noexcept |
| #define __NOEXCEPT_(__exception) noexcept(__exception) |
| #else |
| #define __THROW_EXCEPTION(__exception) do { (void)__exception; CRASH(); } while (0); |
| #define __NOEXCEPT |
| #define __NOEXCEPT_(...) |
| #endif |
| |
| struct __in_place_private{ |
| template<typename> |
| struct __type_holder; |
| |
| template<size_t> |
| struct __value_holder; |
| }; |
| |
| |
| struct in_place_tag { |
| in_place_tag() = delete; |
| }; |
| |
| using in_place_t = in_place_tag(&)(__in_place_private&); |
| |
| template <class _Type> |
| using in_place_type_t = in_place_tag(&)(__in_place_private::__type_holder<_Type>&); |
| |
| template <size_t _Index> |
| using in_place_index_t = in_place_tag(&)(__in_place_private::__value_holder<_Index>&); |
| |
| in_place_tag in_place(__in_place_private&); |
| |
| template <class _Type> |
| in_place_tag in_place(__in_place_private::__type_holder<_Type> &) { |
| __THROW_EXCEPTION(__in_place_private()); |
| } |
| |
| template <size_t _Index> |
| in_place_tag in_place(__in_place_private::__value_holder<_Index> &) { |
| __THROW_EXCEPTION(__in_place_private()); |
| } |
| |
| class bad_variant_access: public std::logic_error{ |
| public: |
| explicit bad_variant_access(const std::string& what_arg): |
| std::logic_error(what_arg) |
| {} |
| explicit bad_variant_access(const char* what_arg): |
| std::logic_error(what_arg) |
| {} |
| }; |
| |
| template<typename T> |
| NO_RETURN_DUE_TO_CRASH inline T __throw_bad_variant_access(const char* what_arg){ |
| __THROW_EXCEPTION(bad_variant_access(what_arg)) |
| } |
| |
| template<ptrdiff_t _Offset,typename _Type,typename ... _Types> |
| struct __type_index_helper; |
| |
| template<ptrdiff_t _Offset,typename _Type,typename _Head,typename ... _Rest> |
| struct __type_index_helper<_Offset,_Type,_Head,_Rest...>{ |
| static constexpr ptrdiff_t __value= |
| __type_index_helper<_Offset+1,_Type,_Rest...>::__value; |
| }; |
| |
| template<ptrdiff_t _Offset,typename _Type,typename ... _Rest> |
| struct __type_index_helper<_Offset,_Type,_Type,_Rest...>{ |
| static constexpr ptrdiff_t __value=_Offset; |
| }; |
| |
| template<typename _Type,typename ... _Types> |
| struct __type_index{ |
| static constexpr ptrdiff_t __value= |
| __type_index_helper<0,_Type,_Types...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __indexed_type; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __indexed_type<0,_Head,_Rest...>{ |
| typedef _Head __type; |
| }; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __indexed_type<-1,_Head,_Rest...>{ |
| typedef void __type; |
| }; |
| |
| template<ptrdiff_t _Index,typename _Head,typename ... _Rest> |
| struct __indexed_type<_Index,_Head,_Rest...>{ |
| typedef typename __indexed_type<_Index-1,_Rest...>::__type __type; |
| }; |
| |
| template<ptrdiff_t _Index,typename ..._Types> |
| struct __next_index{ |
| static constexpr ptrdiff_t __value= |
| (_Index>=ptrdiff_t(sizeof...(_Types)-1))?-1:_Index+1; |
| }; |
| |
| template<typename ... _Types> |
| class Variant; |
| |
| template<typename> |
| struct variant_size; |
| |
| template <typename _Type> |
| struct variant_size<const _Type> : variant_size<_Type> {}; |
| |
| template <typename _Type> |
| struct variant_size<volatile _Type> : variant_size<_Type> {}; |
| |
| template <typename _Type> |
| struct variant_size<const volatile _Type> : variant_size<_Type> {}; |
| |
| template <typename... _Types> |
| struct variant_size<Variant<_Types...>> |
| : std::integral_constant<size_t, sizeof...(_Types)> {}; |
| |
| template<size_t _Index,typename _Type> |
| struct variant_alternative; |
| |
| template<size_t _Index,typename _Type> |
| using variant_alternative_t=typename variant_alternative<_Index,_Type>::type; |
| |
| template <size_t _Index, typename _Type> |
| struct variant_alternative<_Index, const _Type>{ |
| using type=std::add_const_t<variant_alternative_t<_Index,_Type>>; |
| }; |
| |
| template <size_t _Index, typename _Type> |
| struct variant_alternative<_Index, volatile _Type>{ |
| using type=std::add_volatile_t<variant_alternative_t<_Index,_Type>>; |
| }; |
| |
| template <size_t _Index, typename _Type> |
| struct variant_alternative<_Index, volatile const _Type>{ |
| using type=std::add_volatile_t<std::add_const_t<variant_alternative_t<_Index,_Type>>>; |
| }; |
| |
| template<size_t _Index,typename ... _Types> |
| struct variant_alternative<_Index,Variant<_Types...>>{ |
| using type=typename __indexed_type<_Index,_Types...>::__type; |
| }; |
| |
| constexpr size_t variant_npos=-1; |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type& get(Variant<_Types...>&); |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type const& get(Variant<_Types...> const&); |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type&& get(Variant<_Types...>&&); |
| |
| template<typename _Type,typename ... _Types> |
| constexpr const _Type&& get(Variant<_Types...> const&&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type& get(Variant<_Types...>&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type&& get(Variant<_Types...>&&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type const& get( |
| Variant<_Types...> const&); |
| |
| template <ptrdiff_t _Index, typename... _Types> |
| constexpr const typename __indexed_type<_Index, _Types...>::__type && |
| get(Variant<_Types...> const &&); |
| |
| template<typename _Type,typename ... _Types> |
| constexpr std::add_pointer_t<_Type> get_if(Variant<_Types...>&); |
| |
| template<typename _Type,typename ... _Types> |
| constexpr std::add_pointer_t<_Type const> get_if(Variant<_Types...> const&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr std::add_pointer_t<typename __indexed_type<_Index,_Types...>::__type> get_if(Variant<_Types...>&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr std::add_pointer_t<typename __indexed_type<_Index,_Types...>::__type const> get_if( |
| Variant<_Types...> const&); |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __variant_accessor; |
| |
| template<size_t __count, |
| bool __larger_than_char=(__count>SCHAR_MAX), |
| bool __larger_than_short=(__count>SHRT_MAX), |
| bool __larger_than_int=(__count>INT_MAX)> |
| struct __discriminator_type{ |
| typedef signed char __type; |
| }; |
| |
| template<size_t __count> |
| struct __discriminator_type<__count,true,false,false>{ |
| typedef signed short __type; |
| }; |
| |
| template<size_t __count> |
| struct __discriminator_type<__count,true,true,false>{ |
| typedef int __type; |
| }; |
| template<size_t __count> |
| struct __discriminator_type<__count,true,true,true>{ |
| typedef signed long __type; |
| }; |
| |
| template<typename _Type> |
| struct __stored_type{ |
| typedef _Type __type; |
| }; |
| |
| template<typename _Type> |
| struct __stored_type<_Type&>{ |
| typedef _Type* __type; |
| }; |
| |
| template<typename ... _Types> |
| struct __all_trivially_destructible; |
| |
| template<> |
| struct __all_trivially_destructible<> { |
| static constexpr bool __value=true; |
| }; |
| |
| template<typename _Type> |
| struct __all_trivially_destructible<_Type> { |
| static constexpr bool __value= |
| std::is_trivially_destructible<typename __stored_type<_Type>::__type>::value; |
| }; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_trivially_destructible<_Head,_Rest...> { |
| static constexpr bool __value= |
| __all_trivially_destructible<_Head>::__value && |
| __all_trivially_destructible<_Rest...>::__value; |
| }; |
| |
| template<typename _Target,typename ... _Args> |
| struct __storage_nothrow_constructible{ |
| static const bool __value= |
| std::is_nothrow_constructible<_Target, _Args...>::value; |
| }; |
| |
| template<typename ... _Types> |
| struct __storage_nothrow_move_constructible; |
| |
| template<> |
| struct __storage_nothrow_move_constructible<> { |
| static constexpr bool __value=true; |
| }; |
| |
| template<typename _Type> |
| struct __storage_nothrow_move_constructible<_Type> { |
| static constexpr bool __value= |
| std::is_nothrow_move_constructible< |
| typename __stored_type<_Type>::__type>::value; |
| }; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __storage_nothrow_move_constructible<_Head,_Rest...> { |
| static constexpr bool __value= |
| __storage_nothrow_move_constructible<_Head>::__value && |
| __storage_nothrow_move_constructible<_Rest...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __other_storage_nothrow_move_constructible; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __other_storage_nothrow_move_constructible<0,_Head,_Rest...>{ |
| static const bool __value=__storage_nothrow_move_constructible<_Rest...>::__value; |
| }; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __other_storage_nothrow_move_constructible<-1,_Head,_Rest...>{ |
| static const bool __value= |
| __storage_nothrow_move_constructible<_Head,_Rest...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,typename _Head,typename ... _Rest> |
| struct __other_storage_nothrow_move_constructible<_Index,_Head,_Rest...>{ |
| static const bool __value= |
| __storage_nothrow_move_constructible<_Head>::__value && |
| __other_storage_nothrow_move_constructible<_Index-1,_Rest...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __backup_storage_required{ |
| static const bool __value= |
| !__storage_nothrow_move_constructible< |
| typename __indexed_type<_Index,_Types...>::__type>::__value && |
| !__other_storage_nothrow_move_constructible<_Index,_Types...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,ptrdiff_t _Count,typename ... _Types> |
| struct __any_backup_storage_required_impl{ |
| static const bool __value= |
| __backup_storage_required<_Index,_Types...>::__value || |
| __any_backup_storage_required_impl<_Index+1,_Count-1,_Types...>::__value; |
| }; |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __any_backup_storage_required_impl<_Index,0,_Types...>{ |
| static const bool __value=false; |
| }; |
| |
| template<typename _Variant> |
| struct __any_backup_storage_required; |
| |
| template<typename ... _Types> |
| struct __any_backup_storage_required<Variant<_Types...> >{ |
| static const bool __value= |
| __any_backup_storage_required_impl<0,sizeof...(_Types),_Types...>::__value; |
| }; |
| |
| template<typename ... _Types> |
| union __variant_data; |
| |
| template<typename _Type,bool=std::is_literal_type<_Type>::value> |
| struct __variant_storage{ |
| typedef _Type __type; |
| |
| static constexpr _Type& __get(__type& __val){ |
| return __val; |
| } |
| static constexpr _Type&& __get_rref(__type& __val){ |
| return std::move(__val); |
| } |
| static constexpr const _Type& __get(__type const& __val){ |
| return __val; |
| } |
| static constexpr const _Type&& __get_rref(__type const& __val){ |
| return std::move(__val); |
| } |
| static void __destroy(__type&){} |
| }; |
| |
| template<typename _Type> |
| struct __storage_wrapper{ |
| typename std::aligned_storage<sizeof(_Type),alignof(_Type)>::type __storage; |
| |
| template<typename ... _Args> |
| static constexpr void __construct(void* __p,_Args&& ... __args){ |
| new (__p) _Type(std::forward<_Args>(__args)...); |
| } |
| |
| template <typename _Dummy = _Type> |
| __storage_wrapper( |
| typename std::enable_if<std::is_default_constructible<_Dummy>::value, |
| void (__storage_wrapper::*)()>::type = nullptr) { |
| __construct(&__storage); |
| } |
| |
| template <typename _Dummy = _Type> |
| __storage_wrapper( |
| typename std::enable_if<!std::is_default_constructible<_Dummy>::value, |
| void (__storage_wrapper::*)()>::type = nullptr) { |
| } |
| |
| template<typename _First,typename ... _Args> |
| __storage_wrapper(_First&& __first,_Args&& ... __args){ |
| __construct(&__storage,std::forward<_First>(__first),std::forward<_Args>(__args)...); |
| } |
| |
| _Type& __get(){ |
| return *static_cast<_Type*>(static_cast<void*>(&__storage)); |
| } |
| constexpr _Type const& __get() const{ |
| return *static_cast<_Type const*>(static_cast<void const*>(&__storage)); |
| } |
| void __destroy(){ |
| __get().~_Type(); |
| } |
| }; |
| |
| template<typename _Type> |
| struct __storage_wrapper<_Type&>{ |
| _Type* __storage; |
| |
| template<typename _Arg> |
| constexpr __storage_wrapper(_Arg& __arg): |
| __storage(&__arg){} |
| |
| _Type& __get(){ |
| return *__storage; |
| } |
| constexpr _Type const& __get() const{ |
| return *__storage; |
| } |
| }; |
| |
| template<typename _Type> |
| struct __variant_storage<_Type,false>{ |
| typedef __storage_wrapper<_Type> __type; |
| |
| static constexpr _Type& __get(__type& __val){ |
| return __val.__get(); |
| } |
| static constexpr _Type&& __get_rref(__type& __val){ |
| return std::move(__val.__get()); |
| } |
| static constexpr const _Type& __get(__type const& __val){ |
| return __val.__get(); |
| } |
| static constexpr const _Type&& __get_rref(__type const& __val){ |
| return std::move(__val.__get()); |
| } |
| static void __destroy(__type& __val){ |
| __val.__destroy(); |
| } |
| }; |
| |
| template<typename _Type,bool __b> |
| struct __variant_storage<_Type&,__b>{ |
| typedef _Type* __type; |
| |
| static constexpr _Type& __get(__type& __val){ |
| return *__val; |
| } |
| static constexpr _Type& __get_rref(__type& __val){ |
| return *__val; |
| } |
| static constexpr _Type& __get(__type const& __val){ |
| return *__val; |
| } |
| static constexpr _Type& __get_rref(__type const& __val){ |
| return *__val; |
| } |
| static void __destroy(__type&){} |
| }; |
| |
| template<typename _Type,bool __b> |
| struct __variant_storage<_Type&&,__b>{ |
| typedef _Type* __type; |
| |
| static constexpr _Type&& __get(__type& __val){ |
| return static_cast<_Type&&>(*__val); |
| } |
| static constexpr _Type&& __get_rref(__type& __val){ |
| return static_cast<_Type&&>(*__val); |
| } |
| static constexpr _Type&& __get(__type const& __val){ |
| return static_cast<_Type&&>(*__val); |
| } |
| static constexpr _Type&& __get_rref(__type const& __val){ |
| return static_cast<_Type&&>(*__val); |
| } |
| static void __destroy(__type&){} |
| }; |
| |
| template<> |
| union __variant_data<>{ |
| constexpr __variant_data(){} |
| }; |
| |
| template<typename _Type> |
| union __variant_data<_Type>{ |
| typename __variant_storage<_Type>::__type __val; |
| struct __dummy_type{} __dummy; |
| |
| constexpr __variant_data():__dummy(){} |
| |
| template<typename ... _Args> |
| constexpr __variant_data(in_place_index_t<0>,_Args&& ... __args): |
| __val(std::forward<_Args>(__args)...){} |
| |
| _Type& __get(in_place_index_t<0>){ |
| return __variant_storage<_Type>::__get(__val); |
| } |
| /*constexpr*/ _Type&& __get_rref(in_place_index_t<0>){ |
| return __variant_storage<_Type>::__get_rref(__val); |
| } |
| constexpr const _Type& __get(in_place_index_t<0>) const{ |
| return __variant_storage<_Type>::__get(__val); |
| } |
| constexpr const _Type&& __get_rref(in_place_index_t<0>) const{ |
| return __variant_storage<_Type>::__get_rref(__val); |
| } |
| void __destroy(in_place_index_t<0>){ |
| __variant_storage<_Type>::__destroy(__val); |
| } |
| }; |
| |
| template<typename _Type> |
| union __variant_data<_Type&>{ |
| typename __variant_storage<_Type&>::__type __val; |
| struct __dummy_type{} __dummy; |
| |
| constexpr __variant_data():__dummy(){} |
| |
| template<typename ... _Args> |
| constexpr __variant_data(in_place_index_t<0>,_Args&& ... __args): |
| __val(&std::forward<_Args>(__args)...){} |
| |
| _Type& __get(in_place_index_t<0>){ |
| return __variant_storage<_Type&>::__get(__val); |
| } |
| constexpr _Type& __get(in_place_index_t<0>) const{ |
| return __variant_storage<_Type&>::__get(__val); |
| } |
| |
| _Type& __get_rref(in_place_index_t<0>){ |
| return __variant_storage<_Type&>::__get_rref(__val); |
| } |
| constexpr _Type& __get_rref(in_place_index_t<0>) const{ |
| return __variant_storage<_Type&>::__get_rref(__val); |
| } |
| |
| void __destroy(in_place_index_t<0>){ |
| __variant_storage<_Type&>::__destroy(__val); |
| } |
| }; |
| |
| template<typename _Type> |
| union __variant_data<_Type&&>{ |
| typename __variant_storage<_Type&&>::__type __val; |
| struct __dummy_type{} __dummy; |
| |
| constexpr __variant_data():__dummy(){} |
| |
| template<typename _Arg> |
| __variant_data(in_place_index_t<0>,_Arg&& __arg): |
| __val(&__arg){} |
| |
| _Type&& __get(in_place_index_t<0>){ |
| return __variant_storage<_Type&&>::__get(__val); |
| } |
| constexpr _Type&& __get(in_place_index_t<0>) const{ |
| return __variant_storage<_Type&&>::__get(__val); |
| } |
| _Type&& __get_rref(in_place_index_t<0>){ |
| return __variant_storage<_Type&&>::__get_rref(__val); |
| } |
| constexpr _Type&& __get_rref(in_place_index_t<0>) const{ |
| return __variant_storage<_Type&&>::__get_rref(__val); |
| } |
| void __destroy(in_place_index_t<0>){ |
| __variant_storage<_Type&&>::__destroy(__val); |
| } |
| }; |
| |
| template<typename _Head,typename ... _Rest> |
| union __variant_data<_Head,_Rest...>{ |
| __variant_data<_Head> __head; |
| __variant_data<_Rest...> __rest; |
| |
| constexpr __variant_data(): |
| __head(){} |
| |
| template<typename ... _Args> |
| constexpr __variant_data(in_place_index_t<0>,_Args&& ... __args): |
| __head(in_place<0>,std::forward<_Args>(__args)...){} |
| template<size_t _Index,typename ... _Args> |
| constexpr __variant_data(in_place_index_t<_Index>,_Args&& ... __args): |
| __rest(in_place<_Index-1>,std::forward<_Args>(__args)...){} |
| |
| _Head& __get(in_place_index_t<0>){ |
| return __head.__get(in_place<0>); |
| } |
| |
| /*constexpr*/ _Head&& __get_rref(in_place_index_t<0>){ |
| return __head.__get_rref(in_place<0>); |
| } |
| |
| constexpr const _Head& __get(in_place_index_t<0>) const{ |
| return __head.__get(in_place<0>); |
| } |
| |
| constexpr const _Head&& __get_rref(in_place_index_t<0>) const{ |
| return __head.__get_rref(in_place<0>); |
| } |
| |
| template<size_t _Index> |
| typename __indexed_type<_Index-1,_Rest...>::__type& __get( |
| in_place_index_t<_Index>){ |
| return __rest.__get(in_place<_Index-1>); |
| } |
| |
| template<size_t _Index> |
| /*constexpr*/ typename __indexed_type<_Index-1,_Rest...>::__type&& __get_rref( |
| in_place_index_t<_Index>){ |
| return __rest.__get_rref(in_place<_Index-1>); |
| } |
| |
| template<size_t _Index> |
| constexpr const typename __indexed_type<_Index-1,_Rest...>::__type& __get( |
| in_place_index_t<_Index>) const{ |
| return __rest.__get(in_place<_Index-1>); |
| } |
| |
| template<size_t _Index> |
| constexpr const typename __indexed_type<_Index-1,_Rest...>::__type&& __get_rref( |
| in_place_index_t<_Index>) const{ |
| return __rest.__get_rref(in_place<_Index-1>); |
| } |
| |
| |
| void __destroy(in_place_index_t<0>){ |
| __head.__destroy(in_place<0>); |
| } |
| template<size_t _Index> |
| void __destroy(in_place_index_t<_Index>){ |
| __rest.__destroy(in_place<_Index-1>); |
| } |
| }; |
| |
| |
| template<ptrdiff_t... _Indices> |
| struct __index_sequence{ |
| typedef __index_sequence<_Indices...,sizeof...(_Indices)> __next; |
| static constexpr size_t __length=sizeof...(_Indices); |
| }; |
| |
| template<typename ... _Types> |
| struct __type_indices; |
| |
| template<> |
| struct __type_indices<>{ |
| typedef __index_sequence<> __type; |
| }; |
| |
| template<typename _Type> |
| struct __type_indices<_Type>{ |
| typedef __index_sequence<0> __type; |
| }; |
| |
| template<typename _Type,typename ... _Rest> |
| struct __type_indices<_Type,_Rest...>{ |
| typedef typename __type_indices<_Rest...>::__type::__next __type; |
| }; |
| |
| template<typename _Variant> |
| struct __variant_indices; |
| |
| template<typename ... _Types> |
| struct __variant_indices<Variant<_Types...>>{ |
| typedef typename __type_indices<_Types...>::__type __type; |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __move_construct_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __move_construct_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant*,_Variant&); |
| |
| template<ptrdiff_t _Index> |
| static void __move_construct_func( |
| _Variant * __lhs,_Variant& __rhs){ |
| __lhs->template __emplace_construct<_Index>( |
| std::move(get<_Index>(__rhs))); |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __move_construct_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __move_construct_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__move_construct_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __move_assign_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __move_assign_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant*,_Variant&); |
| |
| template<ptrdiff_t _Index> |
| static void __move_assign_func( |
| _Variant * __lhs,_Variant& __rhs){ |
| get<_Index>(*__lhs)=std::move(get<_Index>(__rhs)); |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __move_assign_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __move_assign_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__move_assign_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __copy_construct_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __copy_construct_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant*,_Variant const&); |
| |
| template<ptrdiff_t _Index> |
| static void __copy_construct_func( |
| _Variant * __lhs,_Variant const& __rhs){ |
| __lhs->template __emplace_construct<_Index>( |
| get<_Index>(__rhs)); |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __copy_construct_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __copy_construct_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__copy_construct_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __copy_assign_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __copy_assign_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant*,_Variant const&); |
| |
| template<ptrdiff_t _Index> |
| static void __copy_assign_func( |
| _Variant * __lhs,_Variant const& __rhs){ |
| get<_Index>(*__lhs)=get<_Index>(__rhs); |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __copy_assign_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __copy_assign_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__copy_assign_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __destroy_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __destroy_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant*); |
| |
| template<ptrdiff_t _Index> |
| static void __destroy_func( |
| _Variant * __self){ |
| if(__self->__index>=0){ |
| __self->__storage.__destroy(in_place<_Index>); |
| } |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __destroy_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __destroy_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__destroy_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __swap_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __swap_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __func_type)(_Variant&,_Variant&); |
| |
| template<ptrdiff_t _Index> |
| static void __swap_func( |
| _Variant & __lhs,_Variant & __rhs){ |
| swap(get<_Index>(__lhs),get<_Index>(__rhs)); |
| } |
| |
| static const __func_type __apply[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __swap_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __func_type |
| __swap_op_table<_Variant,__index_sequence<_Indices...>>::__apply[ |
| sizeof...(_Indices)]={ |
| &__swap_func<_Indices>... |
| }; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __equality_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __equality_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef bool(* const __compare_func_type)(_Variant const&,_Variant const&); |
| |
| template<ptrdiff_t _Index> |
| static constexpr bool __equality_compare_func( |
| _Variant const& __lhs,_Variant const& __rhs){ |
| return get<_Index>(__lhs)==get<_Index>(__rhs); |
| } |
| |
| static constexpr __compare_func_type __equality_compare[sizeof...(_Indices)]={ |
| &__equality_compare_func<_Indices>... |
| }; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| constexpr typename __equality_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __compare_func_type |
| __equality_op_table<_Variant,__index_sequence<_Indices...>>::__equality_compare[ |
| sizeof...(_Indices)]; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __less_than_op_table; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __less_than_op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef bool(* const __compare_func_type)(_Variant const&,_Variant const&); |
| |
| template<ptrdiff_t _Index> |
| static constexpr bool __less_than_compare_func( |
| _Variant const& __lhs,_Variant const& __rhs){ |
| return get<_Index>(__lhs)<get<_Index>(__rhs); |
| } |
| |
| static constexpr __compare_func_type __less_than_compare[sizeof...(_Indices)]={ |
| &__less_than_compare_func<_Indices>... |
| }; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| constexpr typename __less_than_op_table<_Variant,__index_sequence<_Indices...>>:: |
| __compare_func_type |
| __less_than_op_table<_Variant,__index_sequence<_Indices...>>::__less_than_compare[ |
| sizeof...(_Indices)]; |
| |
| template<typename _Variant> |
| struct __variant_storage_type; |
| |
| template<typename _Derived,bool __trivial_destructor> |
| struct __variant_base |
| { |
| ~__variant_base(){ |
| static_cast<_Derived*>(this)->__destroy_self(); |
| } |
| }; |
| |
| template<typename _Derived> |
| struct __variant_base<_Derived,true>{ |
| }; |
| |
| |
| template<ptrdiff_t _Offset,typename _CurrentSequence, |
| typename _Type,typename ... _Types> |
| struct __all_indices_helper; |
| |
| template<ptrdiff_t _Offset,ptrdiff_t ... _Indices, |
| typename _Type,typename ... _Rest> |
| struct __all_indices_helper< |
| _Offset,__index_sequence<_Indices...>, |
| _Type,_Type,_Rest...>{ |
| typedef typename __all_indices_helper< |
| _Offset+1,__index_sequence<_Indices...,_Offset>,_Type,_Rest...>::__type |
| __type; |
| }; |
| |
| template<ptrdiff_t _Offset,typename _CurrentSequence, |
| typename _Type,typename _Head,typename ... _Rest> |
| struct __all_indices_helper<_Offset,_CurrentSequence,_Type,_Head,_Rest...>{ |
| typedef typename __all_indices_helper< |
| _Offset+1,_CurrentSequence,_Type,_Rest...>::__type __type; |
| }; |
| |
| template<ptrdiff_t _Offset,typename _CurrentSequence,typename _Type> |
| struct __all_indices_helper<_Offset,_CurrentSequence,_Type>{ |
| typedef _CurrentSequence __type; |
| }; |
| |
| template<typename _Type,typename ... _Types> |
| struct __all_indices{ |
| typedef typename __all_indices_helper< |
| 0,__index_sequence<>,_Type,_Types...>::__type __type; |
| }; |
| |
| template<typename ... _Sequences> |
| struct __combine_sequences; |
| |
| template<ptrdiff_t ... _Indices1,ptrdiff_t ... _Indices2> |
| struct __combine_sequences< |
| __index_sequence<_Indices1...>,__index_sequence<_Indices2...>>{ |
| typedef __index_sequence<_Indices1...,_Indices2...> __type; |
| }; |
| |
| template<typename _Sequence,typename ... _Rest> |
| struct __combine_sequences<_Sequence,_Rest...>{ |
| typedef typename __combine_sequences< |
| _Sequence, |
| typename __combine_sequences<_Rest...>::__type>::__type __type; |
| }; |
| |
| template<typename _Indices> |
| struct __first_index; |
| |
| template<ptrdiff_t _FirstIndex,ptrdiff_t ... _Rest> |
| struct __first_index<__index_sequence<_FirstIndex,_Rest...>>{ |
| static constexpr ptrdiff_t __value=_FirstIndex; |
| }; |
| |
| template<ptrdiff_t _Offset,typename _CurrentSequence, |
| typename _Type,typename ... _Types> |
| struct __constructible_matches_helper; |
| |
| template<ptrdiff_t _Offset,typename _Sequence,typename _Type> |
| struct __constructible_matches_helper< |
| _Offset,_Sequence,_Type>{ |
| typedef _Sequence __type; |
| }; |
| |
| template<bool _Accept,ptrdiff_t _Entry> |
| struct __sequence_or_empty{ |
| typedef __index_sequence<> __type; |
| }; |
| |
| template<ptrdiff_t _Entry> |
| struct __sequence_or_empty<true,_Entry>{ |
| typedef __index_sequence<_Entry> __type; |
| }; |
| |
| template<ptrdiff_t _Offset,typename _CurrentSequence, |
| typename _Type,typename _Head,typename ... _Rest> |
| struct __constructible_matches_helper< |
| _Offset,_CurrentSequence,_Type,_Head,_Rest...>{ |
| typedef |
| typename __constructible_matches_helper< |
| _Offset+1, |
| typename __combine_sequences< |
| _CurrentSequence, |
| typename __sequence_or_empty< |
| std::is_constructible<_Head,_Type>::value, |
| _Offset>::__type>::__type, |
| _Type,_Rest...>::__type __type; |
| }; |
| |
| template<typename _Type,typename ... _Types> |
| struct __constructible_matches{ |
| typedef typename __constructible_matches_helper< |
| 0,__index_sequence<>,_Type,_Types...>::__type __type; |
| }; |
| |
| template<typename _Type,typename ... _Types> |
| struct __type_index_to_construct{ |
| typedef typename __all_indices<_Type,_Types...>::__type __direct_matches; |
| typedef typename __all_indices< |
| typename std::remove_const< |
| typename std::remove_reference<_Type>::type |
| >::type,_Types...>::__type __value_matches; |
| typedef typename __all_indices< |
| _Type, |
| typename std::remove_const< |
| typename std::remove_reference<_Types>::type |
| >::type...>::__type __rref_matches; |
| |
| typedef typename __constructible_matches<_Type,_Types...>::__type |
| __constructibles; |
| |
| static_assert( |
| (__direct_matches::__length>0) || |
| (__value_matches::__length>0) || |
| (__rref_matches::__length>0) || |
| (__constructibles::__length==1), |
| "For conversion construction of variants, exactly one type must be constructible"); |
| |
| typedef typename __combine_sequences< |
| __direct_matches,__value_matches,__rref_matches, |
| __constructibles>::__type __all_matches; |
| |
| static constexpr ptrdiff_t __value=__first_index<__all_matches>::__value; |
| }; |
| |
| struct __replace_construct_helper{ |
| template< |
| ptrdiff_t _Index, |
| bool __construct_directly, |
| bool __indexed_type_has_nothrow_move, |
| bool __other_types_have_nothrow_move> |
| struct __helper; |
| |
| template<typename _Variant, |
| typename _Indices=typename __variant_indices<_Variant>::__type> |
| struct __op_table; |
| }; |
| |
| template< |
| ptrdiff_t _Index, |
| bool __other_types_have_nothrow_move> |
| struct __replace_construct_helper::__helper< |
| _Index,false,true,__other_types_have_nothrow_move>{ |
| |
| template<typename _Variant,typename ... _Args> |
| static void __trampoline(_Variant& __v,_Args&& ... __args){ |
| __v.template __two_stage_replace<_Index>(__args...); |
| } |
| }; |
| |
| template< |
| ptrdiff_t _Index, |
| bool __indexed_type_has_nothrow_move, |
| bool __other_types_have_nothrow_move> |
| struct __replace_construct_helper::__helper< |
| _Index,true,__indexed_type_has_nothrow_move, |
| __other_types_have_nothrow_move>{ |
| |
| template<typename _Variant,typename ... _Args> |
| static void __trampoline(_Variant& __v,_Args&& ... __args){ |
| __v.template __direct_replace<_Index>(std::forward<_Args>(__args)...); |
| } |
| }; |
| |
| |
| template< |
| ptrdiff_t _Index> |
| struct __replace_construct_helper::__helper< |
| _Index,false,false,true>{ |
| |
| template<typename _Variant,typename ... _Args> |
| static void __trampoline(_Variant& __v,_Args&& ... __args){ |
| __v.template __local_backup_replace<_Index>(std::forward<_Args>(__args)...); |
| } |
| }; |
| |
| template< |
| ptrdiff_t _Index> |
| struct __replace_construct_helper::__helper< |
| _Index,false,false,false>{ |
| |
| template<typename _Variant,typename ... _Args> |
| static void __trampoline(_Variant& __v,_Args&& ... __args){ |
| __v.template __direct_replace<_Index>(std::forward<_Args>(__args)...); |
| } |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| struct __replace_construct_helper::__op_table<_Variant,__index_sequence<_Indices...>>{ |
| typedef void(* const __move_func_type)(_Variant*,_Variant&); |
| typedef void(* const __copy_func_type)(_Variant*,_Variant const&); |
| |
| template<ptrdiff_t _Index> |
| static void __move_assign_func( |
| _Variant * __lhs,_Variant& __rhs){ |
| __lhs->template __replace_construct<_Index>(std::move(get<_Index>(__rhs))); |
| __rhs.__destroy_self(); |
| } |
| |
| template<ptrdiff_t _Index> |
| static void __copy_assign_func( |
| _Variant * __lhs,_Variant const& __rhs){ |
| __lhs->template __replace_construct<_Index>(get<_Index>(__rhs)); |
| } |
| |
| static const __move_func_type __move_assign[sizeof...(_Indices)]; |
| static const __copy_func_type __copy_assign[sizeof...(_Indices)]; |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __replace_construct_helper::__op_table< |
| _Variant,__index_sequence<_Indices...>>::__move_func_type |
| __replace_construct_helper::__op_table< |
| _Variant,__index_sequence<_Indices...>>::__move_assign[ |
| sizeof...(_Indices)]={ |
| &__move_assign_func<_Indices>... |
| }; |
| |
| template<typename _Variant,ptrdiff_t ... _Indices> |
| const typename __replace_construct_helper::__op_table< |
| _Variant,__index_sequence<_Indices...>>::__copy_func_type |
| __replace_construct_helper::__op_table< |
| _Variant,__index_sequence<_Indices...>>::__copy_assign[ |
| sizeof...(_Indices)]={ |
| &__copy_assign_func<_Indices>... |
| }; |
| |
| template<ptrdiff_t _Index,ptrdiff_t _MaskIndex,typename _Storage> |
| struct __backup_storage_ops{ |
| static void __move_construct_func( |
| _Storage * __dest,_Storage& __source){ |
| new(__dest) _Storage( |
| in_place<_Index>, |
| std::move(__source.__get(in_place<_Index>))); |
| } |
| static void __destroy_func(_Storage * __obj){ |
| __obj->__destroy(in_place<_Index>); |
| }; |
| }; |
| |
| template<ptrdiff_t _Index,typename _Storage> |
| struct __backup_storage_ops<_Index,_Index,_Storage>{ |
| static void __move_construct_func(_Storage *,_Storage&){ |
| __THROW_EXCEPTION(std::bad_alloc()); |
| }; |
| static void __destroy_func(_Storage *){ |
| __THROW_EXCEPTION(std::bad_alloc()); |
| }; |
| }; |
| |
| template<ptrdiff_t _MaskIndex,typename _Storage,typename _Indices> |
| struct __backup_storage_op_table; |
| |
| template<ptrdiff_t _MaskIndex,typename _Storage,ptrdiff_t ... _Indices> |
| struct __backup_storage_op_table< |
| _MaskIndex,_Storage,__index_sequence<_Indices...> > |
| { |
| typedef void (*__move_func_type)(_Storage * __dest,_Storage& __source); |
| typedef void (*__destroy_func_type)(_Storage * __obj); |
| |
| template<size_t _Index> |
| struct __helper{ |
| typedef __backup_storage_ops<_Index,_MaskIndex,_Storage> __ops; |
| }; |
| |
| static const __move_func_type __move_ops[sizeof...(_Indices)]; |
| static const __destroy_func_type __destroy_ops[sizeof...(_Indices)]; |
| }; |
| |
| template<ptrdiff_t _MaskIndex,typename _Storage,ptrdiff_t ... _Indices> |
| const typename __backup_storage_op_table< |
| _MaskIndex,_Storage,__index_sequence<_Indices...> >::__move_func_type |
| __backup_storage_op_table< |
| _MaskIndex,_Storage,__index_sequence<_Indices...> >::__move_ops[ |
| sizeof...(_Indices)]={ |
| &__helper<_Indices>::__ops::__move_construct_func... |
| }; |
| |
| template<ptrdiff_t _MaskIndex,typename _Storage,ptrdiff_t ... _Indices> |
| const typename __backup_storage_op_table< |
| _MaskIndex,_Storage,__index_sequence<_Indices...> >::__destroy_func_type |
| __backup_storage_op_table< |
| _MaskIndex,_Storage,__index_sequence<_Indices...> >::__destroy_ops[ |
| sizeof...(_Indices)]={ |
| &__helper<_Indices>::__ops::__destroy_func... |
| }; |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __backup_storage{ |
| typedef __variant_data<_Types...> __storage_type; |
| |
| typedef __backup_storage_op_table< |
| _Index,__storage_type,typename __type_indices<_Types...>::__type> |
| __op_table_type; |
| |
| ptrdiff_t __backup_index; |
| __storage_type& __live_storage; |
| __storage_type __backup; |
| |
| __backup_storage(ptrdiff_t __live_index_,__storage_type& __live_storage_): |
| __backup_index(__live_index_),__live_storage(__live_storage_){ |
| if(__backup_index>=0){ |
| __op_table_type::__move_ops[__backup_index]( |
| &__backup,__live_storage); |
| __op_table_type::__destroy_ops[__backup_index]( |
| &__live_storage); |
| } |
| } |
| void __destroy(){ |
| if(__backup_index>=0) |
| __op_table_type::__destroy_ops[__backup_index]( |
| &__backup); |
| __backup_index=-1; |
| } |
| |
| ~__backup_storage(){ |
| if(__backup_index>=0){ |
| __op_table_type::__move_ops[__backup_index]( |
| &__live_storage,__backup); |
| __destroy(); |
| } |
| } |
| }; |
| |
| template<typename ... _Types> |
| struct __all_move_constructible; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_move_constructible<_Head,_Rest...> |
| { |
| static constexpr bool value=std::is_move_constructible<_Head>::value && __all_move_constructible<_Rest...>::value; |
| }; |
| |
| template<> |
| struct __all_move_constructible<>: |
| std::true_type{}; |
| |
| template<typename ... _Types> |
| struct __all_move_assignable; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_move_assignable<_Head,_Rest...> |
| { |
| static constexpr bool value=std::is_move_assignable<_Head>::value && __all_move_assignable<_Rest...>::value; |
| }; |
| |
| template<> |
| struct __all_move_assignable<>: |
| std::true_type{}; |
| |
| template<typename ... _Types> |
| struct __all_copy_assignable; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_copy_assignable<_Head,_Rest...> |
| { |
| static constexpr bool value=std::is_copy_assignable<_Head>::value && __all_copy_assignable<_Rest...>::value; |
| }; |
| |
| template<> |
| struct __all_copy_assignable<>: |
| std::true_type{}; |
| |
| namespace __swap_test_detail{ |
| using std::swap; |
| |
| template<typename _Other> |
| struct __swap_result{}; |
| |
| template<typename> |
| static char __test(...); |
| template <typename _Other> |
| static std::pair<char, std::pair<char, __swap_result<decltype( |
| swap(std::declval<_Other &>(),std::declval<_Other &>()))>>> |
| __test(_Other *); |
| } |
| |
| template <typename _Type> struct __is_swappable { |
| static constexpr bool value = |
| sizeof(__swap_test_detail::__test<_Type>(0)) != 1; |
| }; |
| |
| template<typename ... _Types> |
| struct __all_swappable; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_swappable<_Head,_Rest...> |
| { |
| static constexpr bool value=__is_swappable<_Head>::value && __all_swappable<_Rest...>::value; |
| }; |
| |
| template<> |
| struct __all_swappable<>: |
| std::true_type{}; |
| |
| template<bool _MoveConstructible,typename ... _Types> |
| struct __noexcept_variant_move_construct_impl{}; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __noexcept_variant_move_construct_impl<true,_Head,_Rest...>{ |
| static constexpr bool value=noexcept(_Head(std::declval<_Head&&>())) && __noexcept_variant_move_construct_impl<true,_Rest...>::value; |
| }; |
| |
| template<> |
| struct __noexcept_variant_move_construct_impl<true>{ |
| static constexpr bool value=true; |
| }; |
| |
| template<typename ... _Types> |
| struct __noexcept_variant_move_construct: |
| __noexcept_variant_move_construct_impl<__all_move_constructible<_Types...>::value,_Types...> |
| {}; |
| |
| template<bool _MoveAssignable,typename ... _Types> |
| struct __noexcept_variant_move_assign_impl{}; |
| |
| template <typename _Head, typename... _Rest> |
| struct __noexcept_variant_move_assign_impl<true, _Head, _Rest...> { |
| static constexpr bool value = |
| std::is_nothrow_move_assignable<_Head>::value && |
| std::is_nothrow_move_constructible<_Head>::value && |
| __noexcept_variant_move_assign_impl<true, _Rest...>::value; |
| }; |
| |
| template<> |
| struct __noexcept_variant_move_assign_impl<true>{ |
| static constexpr bool value=true; |
| }; |
| |
| template <typename... _Types> |
| struct __noexcept_variant_move_assign |
| : __noexcept_variant_move_assign_impl< |
| __all_move_assignable<_Types...>::value && |
| __all_move_constructible<_Types...>::value, |
| _Types...> {}; |
| |
| template<typename ... _Types> |
| struct __all_copy_constructible; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __all_copy_constructible<_Head,_Rest...> |
| { |
| static constexpr bool value=std::is_copy_constructible<_Head>::value && __all_copy_constructible<_Rest...>::value; |
| }; |
| |
| template<> |
| struct __all_copy_constructible<>: |
| std::true_type{}; |
| |
| template<bool _CopyConstructible,typename ... _Types> |
| struct __noexcept_variant_const_copy_construct_impl{}; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __noexcept_variant_const_copy_construct_impl<true,_Head,_Rest...>{ |
| static constexpr bool value=noexcept(_Head(std::declval<_Head const&>())) && __noexcept_variant_const_copy_construct_impl<true,_Rest...>::value; |
| }; |
| |
| template<> |
| struct __noexcept_variant_const_copy_construct_impl<true>{ |
| static constexpr bool value=true; |
| }; |
| |
| template<typename ... _Types> |
| struct __noexcept_variant_const_copy_construct: |
| __noexcept_variant_const_copy_construct_impl<__all_copy_constructible<_Types...>::value,_Types...> |
| {}; |
| |
| template<bool _CopyNon_Constructible,typename ... _Types> |
| struct __noexcept_variant_non_const_copy_construct_impl{}; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __noexcept_variant_non_const_copy_construct_impl<true,_Head,_Rest...>{ |
| static constexpr bool value=noexcept(_Head(std::declval<_Head&>())) && __noexcept_variant_non_const_copy_construct_impl<true,_Rest...>::value; |
| }; |
| |
| template<> |
| struct __noexcept_variant_non_const_copy_construct_impl<true>{ |
| static constexpr bool value=true; |
| }; |
| |
| template<typename ... _Types> |
| struct __noexcept_variant_non_const_copy_construct: |
| __noexcept_variant_non_const_copy_construct_impl<__all_copy_constructible<_Types...>::value,_Types...> |
| {}; |
| |
| template<bool _Swappable,typename ... _Types> |
| struct __noexcept_variant_swap_impl{}; |
| |
| template <typename _Head, typename... _Rest> |
| struct __noexcept_variant_swap_impl<true, _Head, _Rest...> { |
| static constexpr bool value = |
| noexcept(swap(std::declval<_Head&>(),std::declval<_Head&>())) && |
| __noexcept_variant_swap_impl<true, _Rest...>::value; |
| }; |
| |
| template<> |
| struct __noexcept_variant_swap_impl<true>{ |
| static constexpr bool value=true; |
| }; |
| |
| template<typename ... _Types> |
| struct __noexcept_variant_swap: |
| __noexcept_variant_swap_impl<__all_swappable<_Types...>::value,_Types...> |
| {}; |
| |
| template<typename ... _Types> |
| class Variant: |
| private __variant_base< |
| Variant<_Types...>,__all_trivially_destructible<_Types...>::__value> |
| { |
| typedef __variant_base<Variant<_Types...>,__all_trivially_destructible<_Types...>::__value> __base_type; |
| friend __base_type; |
| friend struct __copy_construct_op_table<Variant>; |
| friend struct __copy_assign_op_table<Variant>; |
| friend struct __move_construct_op_table<Variant>; |
| friend struct __move_assign_op_table<Variant>; |
| friend struct __destroy_op_table<Variant>; |
| |
| template<ptrdiff_t _Index,typename ... _Types2> |
| friend struct __variant_accessor; |
| |
| friend struct __replace_construct_helper; |
| |
| typedef __variant_data<_Types...> __storage_type; |
| __storage_type __storage; |
| typename __discriminator_type<sizeof ... (_Types)>::__type __index; |
| |
| template<size_t _Index,typename ... _Args> |
| size_t __emplace_construct(_Args&& ... __args){ |
| new(&__storage) __storage_type( |
| in_place<_Index>,std::forward<_Args>(__args)...); |
| return _Index; |
| } |
| |
| void __destroy_self(){ |
| if(valueless_by_exception()) |
| return; |
| __destroy_op_table<Variant>::__apply[index()](this); |
| __index=-1; |
| } |
| |
| ptrdiff_t __move_construct(Variant& __other){ |
| ptrdiff_t const __other_index=__other.index(); |
| if(__other_index==-1) |
| return -1; |
| __move_construct_op_table<Variant>::__apply[__other_index](this,__other); |
| __other.__destroy_self(); |
| return __other_index; |
| } |
| |
| ptrdiff_t __copy_construct(Variant const& __other){ |
| ptrdiff_t const __other_index=__other.index(); |
| if(__other_index==-1) |
| return -1; |
| __copy_construct_op_table<Variant>::__apply[__other_index](this,__other); |
| return __other_index; |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| void __replace_construct(_Args&& ... __args){ |
| typedef typename __indexed_type<_Index,_Types...>::__type __this_type; |
| __replace_construct_helper::__helper< |
| _Index, |
| __storage_nothrow_constructible<__this_type,_Args...>::__value || |
| (sizeof...(_Types)==1), |
| __storage_nothrow_move_constructible<__this_type>::__value, |
| __other_storage_nothrow_move_constructible< |
| _Index,_Types...>::__value |
| >::__trampoline(*this,std::forward<_Args>(__args)...); |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| void __two_stage_replace(_Args&& ... __args){ |
| typedef typename __indexed_type<_Index,_Types...>::__type __type; |
| __variant_data<__type> __local( |
| in_place<0>,std::forward<_Args>(__args)...); |
| __destroy_self(); |
| __emplace_construct<_Index>( |
| std::move(__local.__get(in_place<0>))); |
| __index=_Index; |
| __local.__destroy(in_place<0>); |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| void __local_backup_replace(_Args&& ... __args){ |
| __backup_storage<_Index,_Types...> __backup(__index,__storage); |
| __emplace_construct<_Index>(std::forward<_Args>(__args)...); |
| __index=_Index; |
| __backup.__destroy(); |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| void __direct_replace(_Args&& ... __args) { |
| __destroy_self(); |
| __emplace_construct<_Index>(std::forward<_Args>(__args)...); |
| __index=_Index; |
| } |
| |
| struct __private_type{}; |
| |
| public: |
| constexpr Variant() |
| __NOEXCEPT_(noexcept(typename __indexed_type<0,_Types...>::__type())): |
| __storage(in_place<0>), |
| __index(0) |
| {} |
| |
| constexpr Variant(typename std::conditional<__all_move_constructible<_Types...>::value,Variant,__private_type>::type&& __other) |
| __NOEXCEPT_(__noexcept_variant_move_construct<_Types...>::value): |
| __index(__move_construct(__other)) |
| {} |
| |
| constexpr Variant(typename std::conditional<!__all_move_constructible<_Types...>::value,Variant,__private_type>::type&& __other)=delete; |
| |
| constexpr Variant(typename std::conditional<__all_copy_constructible<_Types...>::value,Variant,__private_type>::type& __other) |
| __NOEXCEPT_(__noexcept_variant_non_const_copy_construct<_Types...>::value): |
| __index(__copy_construct(__other)) |
| {} |
| |
| constexpr Variant(typename std::conditional<!__all_copy_constructible<_Types...>::value,Variant,__private_type>::type& __other)=delete; |
| |
| constexpr Variant(typename std::conditional<__all_copy_constructible<_Types...>::value,Variant,__private_type>::type const& __other) |
| __NOEXCEPT_(__noexcept_variant_const_copy_construct<_Types...>::value): |
| __index(__copy_construct(__other)) |
| {} |
| |
| constexpr Variant(typename std::conditional<!__all_copy_constructible<_Types...>::value,Variant,__private_type>::type const& __other)=delete; |
| |
| template<typename _Type,typename ... _Args> |
| explicit constexpr Variant(in_place_type_t<_Type>,_Args&& ... __args): |
| __storage( |
| in_place<__type_index<_Type,_Types...>::__value>, |
| std::forward<_Args>(__args)...), |
| __index(__type_index<_Type,_Types...>::__value) |
| { |
| static_assert(std::is_constructible<_Type,_Args...>::value,"Type must be constructible from args"); |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| explicit constexpr Variant(in_place_index_t<_Index>,_Args&& ... __args): |
| __storage(in_place<_Index>,std::forward<_Args>(__args)...), |
| __index(_Index) |
| { |
| static_assert(std::is_constructible<typename __indexed_type<_Index,_Types...>::__type,_Args...>::value,"Type must be constructible from args"); |
| } |
| |
| template<typename _Type> |
| constexpr Variant(_Type&& __x): |
| __storage( |
| in_place< |
| __type_index_to_construct<_Type,_Types...>::__value>, |
| std::forward<_Type>(__x)), |
| __index(__type_index_to_construct<_Type,_Types...>::__value) |
| {} |
| |
| template<typename _Type, |
| typename _Enable= |
| typename std::enable_if< |
| (__constructible_matches<std::initializer_list<_Type>,_Types...>::__type::__length>0) |
| >::type> |
| constexpr Variant(std::initializer_list<_Type> __x): |
| __storage( |
| in_place< |
| __type_index_to_construct<std::initializer_list<_Type>,_Types...>::__value>, |
| __x), |
| __index(__type_index_to_construct<std::initializer_list<_Type>,_Types...>::__value) |
| {} |
| |
| template<typename _Type> |
| Variant& operator=(_Type&& __x){ |
| constexpr size_t _Index= |
| __type_index_to_construct<_Type,_Types...>::__value; |
| if(_Index==__index){ |
| get<_Index>(*this)=std::forward<_Type>(__x); |
| } |
| else{ |
| __replace_construct<_Index>(std::forward<_Type>(__x)); |
| } |
| return *this; |
| } |
| |
| Variant &operator=( |
| typename std::conditional< |
| !(__all_copy_constructible<_Types...>::value && |
| __all_move_constructible<_Types...>::value && |
| __all_copy_assignable<_Types...>::value), |
| Variant, __private_type>::type const &__other) = delete; |
| |
| Variant &operator=( |
| typename std::conditional< |
| __all_copy_constructible<_Types...>::value && |
| __all_move_constructible<_Types...>::value && |
| __all_copy_assignable<_Types...>::value, |
| Variant, __private_type>::type const &__other) { |
| if (__other.valueless_by_exception()) { |
| __destroy_self(); |
| } |
| else if(__other.index()==index()){ |
| __copy_assign_op_table<Variant>::__apply[index()](this,__other); |
| } |
| else{ |
| __replace_construct_helper::__op_table<Variant>::__copy_assign[ |
| __other.index()](this,__other); |
| } |
| return *this; |
| } |
| Variant &operator=( |
| typename std::conditional< |
| !(__all_copy_constructible<_Types...>::value && |
| __all_move_constructible<_Types...>::value && |
| __all_copy_assignable<_Types...>::value), |
| Variant, __private_type>::type &__other) = delete; |
| |
| Variant &operator=( |
| typename std::conditional< |
| __all_copy_constructible<_Types...>::value && |
| __all_move_constructible<_Types...>::value && |
| __all_copy_assignable<_Types...>::value, |
| Variant, __private_type>::type &__other) { |
| if(__other.valueless_by_exception()){ |
| __destroy_self(); |
| } |
| else if(__other.index()==index()){ |
| __copy_assign_op_table<Variant>::__apply[index()](this,__other); |
| } |
| else{ |
| __replace_construct_helper::__op_table<Variant>::__copy_assign[ |
| __other.index()](this,__other); |
| } |
| return *this; |
| } |
| Variant &operator=( |
| typename std::conditional< |
| !(__all_move_constructible<_Types...>::value && |
| __all_move_assignable<_Types...>::value), |
| Variant, __private_type>::type &&__other) = delete; |
| |
| Variant &operator=( |
| typename std::conditional<__all_move_constructible<_Types...>::value && |
| __all_move_assignable<_Types...>::value, |
| Variant, __private_type>::type && |
| __other) __NOEXCEPT_(__noexcept_variant_move_assign<_Types...>::value) { |
| if (__other.valueless_by_exception()) { |
| __destroy_self(); |
| } |
| else if(__other.index()==index()){ |
| __move_assign_op_table<Variant>::__apply[index()](this,__other); |
| __other.__destroy_self(); |
| } |
| else{ |
| __replace_construct_helper::__op_table<Variant>::__move_assign[ |
| __other.index()](this,__other); |
| } |
| return *this; |
| } |
| |
| template<typename _Type,typename ... _Args> |
| void emplace(_Args&& ... __args){ |
| __direct_replace<__type_index<_Type,_Types...>::__value>( |
| std::forward<_Args>(__args)...); |
| } |
| |
| template<size_t _Index,typename ... _Args> |
| void emplace(_Args&& ... __args){ |
| __direct_replace<_Index>(std::forward<_Args>(__args)...); |
| } |
| |
| constexpr bool valueless_by_exception() const __NOEXCEPT{ |
| return __index==-1; |
| } |
| constexpr ptrdiff_t index() const __NOEXCEPT{ |
| return __index; |
| } |
| |
| void swap( |
| typename std::conditional< |
| __all_swappable<_Types...>::value && |
| __all_move_constructible<_Types...>::value, |
| Variant, __private_type>::type |
| &__other) __NOEXCEPT_(__noexcept_variant_swap<_Types...>::value) { |
| if (__other.index() == index()) { |
| if(!valueless_by_exception()) |
| __swap_op_table<Variant>::__apply[index()](*this,__other); |
| } |
| else{ |
| Variant __temp(std::move(__other)); |
| __other.__index=__other.__move_construct(*this); |
| __index=__move_construct(__temp); |
| } |
| } |
| }; |
| |
| template<> |
| class Variant<>{ |
| public: |
| Variant()=delete; |
| |
| constexpr bool valueless_by_exception() const __NOEXCEPT{ |
| return true; |
| } |
| constexpr ptrdiff_t index() const __NOEXCEPT{ |
| return -1; |
| } |
| |
| void swap(Variant&){} |
| }; |
| |
| template <typename... _Types> |
| typename std::enable_if<__all_swappable<_Types...>::value && |
| __all_move_constructible<_Types...>::value, |
| void>::type |
| swap(Variant<_Types...> &__lhs, Variant<_Types...> &__rhs) __NOEXCEPT_( |
| __noexcept_variant_swap<_Types...>::value) { |
| __lhs.swap(__rhs); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| struct __variant_accessor{ |
| typedef typename __indexed_type<_Index,_Types...>::__type __type; |
| static constexpr __type& get(Variant<_Types...>& __v){ |
| return __v.__storage.__get(in_place<_Index>); |
| } |
| static constexpr __type const& get(Variant<_Types...> const& __v){ |
| return __v.__storage.__get(in_place<_Index>); |
| } |
| static constexpr __type&& get(Variant<_Types...>&& __v){ |
| return __v.__storage.__get_rref(in_place<_Index>); |
| } |
| static constexpr const __type&& get(Variant<_Types...> const&& __v){ |
| return __v.__storage.__get_rref(in_place<_Index>); |
| } |
| }; |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type& get(Variant<_Types...>& __v){ |
| return get<__type_index<_Type,_Types...>::__value>(__v); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type&& get(Variant<_Types...>&& __v){ |
| return get<__type_index<_Type,_Types...>::__value>(std::move(__v)); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr _Type const& get(Variant<_Types...> const& __v){ |
| return get<__type_index<_Type,_Types...>::__value>(__v); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr const _Type&& get(Variant<_Types...> const&& __v){ |
| return get<__type_index<_Type,_Types...>::__value>(std::move(__v)); |
| } |
| |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type const& get(Variant<_Types...> const& __v){ |
| return *( |
| (_Index!=__v.index()) |
| ? std::addressof(__throw_bad_variant_access<typename __indexed_type<_Index,_Types...>::__type const&>("Bad Variant index in get")) |
| : std::addressof(__variant_accessor<_Index,_Types...>::get(__v)) |
| ); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type& get(Variant<_Types...>& __v){ |
| return *( |
| (_Index!=__v.index()) |
| ? std::addressof(__throw_bad_variant_access<typename __indexed_type<_Index,_Types...>::__type&>("Bad Variant index in get")) |
| : std::addressof(__variant_accessor<_Index,_Types...>::get(__v)) |
| ); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr typename __indexed_type<_Index,_Types...>::__type&& get(Variant<_Types...>&& __v){ |
| return __variant_accessor<_Index,_Types...>::get( |
| (((_Index!=__v.index()) ? __throw_bad_variant_access<int>("Bad Variant index in get") : 0), std::move(__v)) |
| ); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr const typename __indexed_type<_Index,_Types...>::__type&& get(Variant<_Types...> const&& __v){ |
| return __variant_accessor<_Index,_Types...>::get( |
| (((_Index!=__v.index()) ? __throw_bad_variant_access<int>("Bad Variant index in get") : 0), std::move(__v)) |
| ); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr std::add_pointer_t<_Type> get_if(Variant<_Types...>& __v){ |
| return (__type_index<_Type,_Types...>::__value!=__v.index())?nullptr:std::addressof(get<_Type>(__v)); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr std::add_pointer_t<_Type const> get_if(Variant<_Types...> const& __v){ |
| return (__type_index<_Type,_Types...>::__value!=__v.index())?nullptr:std::addressof(get<_Type>(__v)); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr std::add_pointer_t<typename __indexed_type<_Index,_Types...>::__type> get_if(Variant<_Types...>& __v){ |
| return ((_Index!=__v.index())?nullptr: |
| std::addressof(__variant_accessor<_Index,_Types...>::get(__v))); |
| } |
| |
| template<ptrdiff_t _Index,typename ... _Types> |
| constexpr std::add_pointer_t<typename __indexed_type<_Index,_Types...>::__type const> get_if( |
| Variant<_Types...> const& __v){ |
| return ((_Index!=__v.index())?nullptr: |
| std::addressof(__variant_accessor<_Index,_Types...>::get(__v))); |
| } |
| |
| template<typename _Type,typename ... _Types> |
| constexpr bool holds_alternative(Variant<_Types...> const& __v) __NOEXCEPT{ |
| return __v.index()==__type_index<_Type,_Types...>::__value; |
| } |
| |
| template<typename _Visitor,typename ... _Types> |
| struct __visitor_return_type; |
| |
| template<typename _Visitor> |
| struct __visitor_return_type<_Visitor>{ |
| typedef decltype(std::declval<_Visitor&>()()) __type; |
| }; |
| |
| template<typename _Visitor,typename _Head,typename ... _Rest> |
| struct __visitor_return_type<_Visitor,_Head,_Rest...>{ |
| typedef decltype(std::declval<_Visitor&>()(std::declval<_Head&>())) __type; |
| }; |
| |
| template<typename _Visitor,typename ... _Types> |
| struct __visitor_table{ |
| typedef Variant<_Types...> __variant_type; |
| typedef typename __visitor_return_type<_Visitor,_Types...>::__type __return_type; |
| typedef __return_type (*__func_type)(_Visitor&,__variant_type&); |
| |
| template<typename _Type> |
| static __return_type __trampoline_func(_Visitor& __visitor,__variant_type& __v){ |
| return __visitor(get<_Type>(__v)); |
| } |
| |
| static const __func_type __trampoline[sizeof...(_Types)]; |
| }; |
| |
| template<typename _Visitor,typename ... _Types> |
| const typename __visitor_table<_Visitor,_Types...>::__func_type __visitor_table<_Visitor,_Types...>::__trampoline[sizeof...(_Types)]={ |
| &__trampoline_func<_Types>... |
| }; |
| |
| template<typename _Visitor,typename ... _Types> |
| constexpr typename __visitor_return_type<_Visitor,_Types...>::__type |
| visit(_Visitor&& __visitor,Variant<_Types...>& __v){ |
| return (__v.valueless_by_exception()) |
| ? __throw_bad_variant_access<typename __visitor_return_type<_Visitor,_Types...>::__type>("Visiting of empty Variant") |
| : __visitor_table<_Visitor,_Types...>::__trampoline[__v.index()](__visitor,__v); |
| } |
| |
| template<typename _Visitor,typename ... _Variants> |
| struct __multi_visitor_return_type{ |
| typedef decltype(std::declval<_Visitor&>()(get<0>(std::declval<_Variants>())...)) |
| __type; |
| }; |
| |
| template<size_t _VariantIndex,typename _Indices> |
| struct __visit_helper; |
| |
| template<ptrdiff_t ... _Indices> |
| struct __visit_helper<0,__index_sequence<_Indices...>>{ |
| template<typename _Visitor,typename ... _Variants> |
| static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type |
| __visit(_Visitor& __visitor,_Variants& ... __v){ |
| return __visitor(get<_Indices>(__v)...); |
| } |
| }; |
| |
| template<size_t _Index,typename ... _Args> |
| struct __arg_selector_t; |
| |
| template<typename _Head,typename ... _Rest> |
| struct __arg_selector_t<0,_Head,_Rest...>{ |
| typedef _Head __type; |
| |
| static constexpr __type& __select(_Head& __head,_Rest& ...){ |
| return __head; |
| } |
| }; |
| |
| template<size_t _Index,typename _Head,typename ... _Rest> |
| struct __arg_selector_t<_Index,_Head,_Rest...>{ |
| typedef typename __arg_selector_t<_Index-1,_Rest...>::__type __type; |
| static constexpr __type& __select(_Head&,_Rest& ... __rest){ |
| return __arg_selector_t<_Index-1,_Rest...>::__select(__rest...); |
| } |
| }; |
| |
| template<size_t _Index,typename ... _Args> |
| constexpr typename __arg_selector_t<_Index,_Args...>::__type&& __arg_selector(_Args&& ... __args){ |
| return std::forward<typename __arg_selector_t<_Index,_Args...>::__type>( |
| __arg_selector_t<_Index,_Args...>::__select(__args...)); |
| } |
| |
| template<ptrdiff_t _Index,size_t _VariantIndex,ptrdiff_t ... _Indices> |
| struct __visit_helper2{ |
| template<typename _Visitor,typename ... _Variants> |
| static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type |
| __visit(_Visitor& __visitor,_Variants&& ... __v){ |
| return (__arg_selector<_VariantIndex-1>(__v...).index()==_Index) |
| ? __visit_helper<_VariantIndex-1,__index_sequence<_Index,_Indices...>>::__visit(__visitor,std::forward<_Variants>(__v)...) |
| : __visit_helper2<_Index-1,_VariantIndex,_Indices...>::__visit(__visitor,std::forward<_Variants>(__v)...); |
| } |
| }; |
| |
| template<size_t _VariantIndex,ptrdiff_t ... _Indices> |
| struct __visit_helper2<-1,_VariantIndex,_Indices...>{ |
| template<typename _Visitor,typename ... _Variants> |
| static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type |
| __visit(_Visitor&,_Variants&& ...){ |
| return __throw_bad_variant_access<typename __multi_visitor_return_type<_Visitor,_Variants...>::__type>("Visiting of empty Variant"); |
| } |
| }; |
| |
| template<typename _Variant> |
| struct __variant_type_count; |
| |
| template<typename ... _Types> |
| struct __variant_type_count<Variant<_Types...>>{ |
| static constexpr size_t __value=sizeof...(_Types); |
| }; |
| |
| template<typename _Variant> |
| struct __variant_type_count<_Variant&>{ |
| static constexpr size_t __value=__variant_type_count<_Variant>::__value; |
| }; |
| |
| template<typename _Variant> |
| struct __variant_type_count<_Variant const&>{ |
| static constexpr size_t __value=__variant_type_count<_Variant>::__value; |
| }; |
| |
| template<size_t _VariantIndex,ptrdiff_t ... _Indices> |
| struct __visit_helper<_VariantIndex,__index_sequence<_Indices...>>{ |
| |
| template<typename _Visitor,typename ... _Variants> |
| static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type |
| __visit(_Visitor& __visitor,_Variants&& ... __v){ |
| return __visit_helper2< |
| __variant_type_count< |
| typename __arg_selector_t< |
| _VariantIndex-1,_Variants...>::__type>::__value-1, |
| _VariantIndex,_Indices...>::__visit( |
| __visitor,std::forward<_Variants&&>(__v)...); |
| } |
| }; |
| |
| template<typename _Visitor,typename ... _Variants> |
| constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type |
| visit(_Visitor&& __visitor,_Variants&& ... __v){ |
| return __visit_helper<sizeof...(_Variants),__index_sequence<>>::__visit( |
| __visitor,std::forward<_Variants>(__v)...); |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator==(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return (__lhs.index()==__rhs.index()) && |
| ((__lhs.index()==-1) || |
| __equality_op_table<Variant<_Types...>>::__equality_compare[__lhs.index()]( |
| __lhs,__rhs)); |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator!=(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return !(__lhs==__rhs); |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator<(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return (__lhs.index()<__rhs.index()) || |
| ((__lhs.index()==__rhs.index()) && |
| ((__lhs.index()!=-1) && |
| __less_than_op_table<Variant<_Types...>>:: |
| __less_than_compare[__lhs.index()](__lhs,__rhs))); |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator>(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return __rhs<__lhs; |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator>=(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return !(__lhs<__rhs); |
| } |
| |
| template<typename ... _Types> |
| constexpr bool operator<=(Variant<_Types...> const& __lhs,Variant<_Types...> const& __rhs){ |
| return !(__lhs>__rhs); |
| } |
| |
| struct Monostate{}; |
| |
| constexpr inline bool operator==(Monostate const&,Monostate const&){ return true;} |
| constexpr inline bool operator!=(Monostate const&,Monostate const&){ return false;} |
| constexpr inline bool operator>=(Monostate const&,Monostate const&){ return true;} |
| constexpr inline bool operator<=(Monostate const&,Monostate const&){ return true;} |
| constexpr inline bool operator>(Monostate const&,Monostate const&){ return false;} |
| constexpr inline bool operator<(Monostate const&,Monostate const&){ return false;} |
| |
| struct __hash_visitor{ |
| template<typename _Type> |
| size_t operator()(_Type const& __x){ |
| return std::hash<_Type>()(__x); |
| } |
| }; |
| |
| // -- WebKit Additions -- |
| |
| template<class V, class... F> |
| auto switchOn(V&& v, F&&... f) -> decltype(visit(makeVisitor(std::forward<F>(f)...), std::forward<V>(v))) |
| { |
| return visit(makeVisitor(std::forward<F>(f)...), std::forward<V>(v)); |
| } |
| |
| } // namespace WTF |
| |
| namespace std { |
| |
| template<> |
| struct hash<WTF::Monostate>{ |
| size_t operator()(WTF::Monostate) __NOEXCEPT{ |
| return 42; |
| } |
| }; |
| |
| template<typename ... _Types> |
| struct hash<WTF::Variant<_Types...>>{ |
| size_t operator()(WTF::Variant<_Types...> const &v) __NOEXCEPT { |
| return std::hash<ptrdiff_t>()(v.index()) ^ WTF::visit(WTF::__hash_visitor(), v); |
| } |
| }; |
| |
| } // namespace std |
| |
| using WTF::Monostate; |
| using WTF::Variant; |
| |
| #endif // !COMPILER(CLANG) || WTF_CPP_STD_VER >= 14 |
| |
| #if COMPILER(MSVC) |
| #pragma warning(pop) |
| #endif |