diff --git a/libcxx/include/variant b/libcxx/include/variant --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -435,30 +435,166 @@ namespace __visitation { struct __base { - template + template inline _LIBCPP_INLINE_VISIBILITY static constexpr decltype(auto) - __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { - constexpr auto __fdiagonal = - __make_fdiagonal<_Visitor&&, - decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); - return __fdiagonal[__index](_VSTD::forward<_Visitor>(__visitor), - _VSTD::forward<_Vs>(__vs).__as_base()...); + __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vp&& __v, _Wp&& __w) { + return __dispatch_at<0>(__index, + _VSTD::forward<_Visitor>(__visitor), + _VSTD::forward<_Vp>(__v).__as_base(), + _VSTD::forward<_Wp>(__w).__as_base()); } template inline _LIBCPP_INLINE_VISIBILITY static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor, _Vs&&... __vs) { - constexpr auto __fmatrix = - __make_fmatrix<_Visitor&&, - decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); - return __at(__fmatrix, __vs.index()...)( - _VSTD::forward<_Visitor>(__visitor), - _VSTD::forward<_Vs>(__vs).__as_base()...); + if constexpr (sizeof...(_Vs) <= 2) { + return __dispatch<0>(index_sequence<>{}, + _VSTD::forward<_Visitor>(__visitor), + _VSTD::forward<_Vs>(__vs).__as_base()...); + } else { + constexpr auto __fmatrix = + __make_fmatrix<_Visitor&&, + decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); + return __at(__fmatrix, __vs.index()...)( + _VSTD::forward<_Visitor>(__visitor), + _VSTD::forward<_Vs>(__vs).__as_base()...); + } } private: + template + inline _LIBCPP_INLINE_VISIBILITY + static constexpr decltype(auto) + __dispatch_at(size_t __index, _Fp&& __f, _Vp&& __v, _Wp&& __w) { + static_assert(__uncvref_t<_Vp>::__size() == __uncvref_t<_Wp>::__size()); + switch (__index) { +#define _LIBCPP_VARIANT_DISPATCH(_Ip) \ + if constexpr (_Ip < __uncvref_t<_Vp>::__size()) { \ + return __invoke_constexpr( \ + _VSTD::forward<_Fp>(__f), \ + __access::__base::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)), \ + __access::__base::__get_alt<_Ip>(_VSTD::forward<_Wp>(__w))); \ + } else { \ + _LIBCPP_UNREACHABLE(); \ + } +#define _LIBCPP_VARIANT_DEFAULT(_Ip) \ + if constexpr (_Ip < __uncvref_t<_Vp>::__size()) { \ + return __dispatch_at<_Ip>(__index, \ + _VSTD::forward<_Fp>(__f), \ + _VSTD::forward<_Vp>(__v), \ + _VSTD::forward<_Wp>(__w)); \ + } else { \ + _LIBCPP_UNREACHABLE(); \ + } + case _Base + 0: _LIBCPP_VARIANT_DISPATCH(_Base + 0); + case _Base + 1: _LIBCPP_VARIANT_DISPATCH(_Base + 1); + case _Base + 2: _LIBCPP_VARIANT_DISPATCH(_Base + 2); + case _Base + 3: _LIBCPP_VARIANT_DISPATCH(_Base + 3); + case _Base + 4: _LIBCPP_VARIANT_DISPATCH(_Base + 4); + case _Base + 5: _LIBCPP_VARIANT_DISPATCH(_Base + 5); + case _Base + 6: _LIBCPP_VARIANT_DISPATCH(_Base + 6); + case _Base + 7: _LIBCPP_VARIANT_DISPATCH(_Base + 7); + case _Base + 8: _LIBCPP_VARIANT_DISPATCH(_Base + 8); + case _Base + 9: _LIBCPP_VARIANT_DISPATCH(_Base + 9); + case _Base + 10: _LIBCPP_VARIANT_DISPATCH(_Base + 10); + case _Base + 11: _LIBCPP_VARIANT_DISPATCH(_Base + 11); + case _Base + 12: _LIBCPP_VARIANT_DISPATCH(_Base + 12); + case _Base + 13: _LIBCPP_VARIANT_DISPATCH(_Base + 13); + case _Base + 14: _LIBCPP_VARIANT_DISPATCH(_Base + 14); + case _Base + 15: _LIBCPP_VARIANT_DISPATCH(_Base + 15); + case _Base + 16: _LIBCPP_VARIANT_DISPATCH(_Base + 16); + case _Base + 17: _LIBCPP_VARIANT_DISPATCH(_Base + 17); + case _Base + 18: _LIBCPP_VARIANT_DISPATCH(_Base + 18); + case _Base + 19: _LIBCPP_VARIANT_DISPATCH(_Base + 19); + case _Base + 20: _LIBCPP_VARIANT_DISPATCH(_Base + 20); + case _Base + 21: _LIBCPP_VARIANT_DISPATCH(_Base + 21); + case _Base + 22: _LIBCPP_VARIANT_DISPATCH(_Base + 22); + case _Base + 23: _LIBCPP_VARIANT_DISPATCH(_Base + 23); + case _Base + 24: _LIBCPP_VARIANT_DISPATCH(_Base + 24); + case _Base + 25: _LIBCPP_VARIANT_DISPATCH(_Base + 25); + case _Base + 26: _LIBCPP_VARIANT_DISPATCH(_Base + 26); + case _Base + 27: _LIBCPP_VARIANT_DISPATCH(_Base + 27); + case _Base + 28: _LIBCPP_VARIANT_DISPATCH(_Base + 28); + case _Base + 29: _LIBCPP_VARIANT_DISPATCH(_Base + 29); + case _Base + 30: _LIBCPP_VARIANT_DISPATCH(_Base + 30); + case _Base + 31: _LIBCPP_VARIANT_DISPATCH(_Base + 31); + default: _LIBCPP_VARIANT_DEFAULT(_Base + 32); +#undef _LIBCPP_VARIANT_DEFAULT +#undef _LIBCPP_VARIANT_DISPATCH + } + } + + template + inline _LIBCPP_INLINE_VISIBILITY + static constexpr decltype(auto) + __dispatch(index_sequence<_Is...>, _Fp&& __f, _Vs&&... __vs) { + if constexpr (sizeof...(_Is) == sizeof...(_Vs)) { + return __invoke_constexpr( + _VSTD::forward<_Fp>(__f), + __access::__base::__get_alt<_Is>(_VSTD::forward<_Vs>(__vs))...); + } else { + return [](_Fp&& __f, auto&& __v, auto&&... __vs) { + switch (__v.index()) { +#define _LIBCPP_VARIANT_DISPATCH(_Ip) \ + if constexpr (_Ip < __uncvref_t::__size()) { \ + return __dispatch<0>(index_sequence<_Is..., _Ip>{}, \ + _VSTD::forward<_Fp>(__f), \ + _VSTD::forward(__vs)..., \ + _VSTD::forward(__v)); \ + } else { \ + _LIBCPP_UNREACHABLE(); \ + } +#define _LIBCPP_VARIANT_DEFAULT(_Ip) \ + if constexpr (_Ip < __uncvref_t::__size()) { \ + return __dispatch<_Ip>(index_sequence<_Is...>{}, \ + _VSTD::forward<_Fp>(__f), \ + _VSTD::forward(__v), \ + _VSTD::forward(__vs)...); \ + } else { \ + _LIBCPP_UNREACHABLE(); \ + } + case _Base + 0: _LIBCPP_VARIANT_DISPATCH(_Base + 0); + case _Base + 1: _LIBCPP_VARIANT_DISPATCH(_Base + 1); + case _Base + 2: _LIBCPP_VARIANT_DISPATCH(_Base + 2); + case _Base + 3: _LIBCPP_VARIANT_DISPATCH(_Base + 3); + case _Base + 4: _LIBCPP_VARIANT_DISPATCH(_Base + 4); + case _Base + 5: _LIBCPP_VARIANT_DISPATCH(_Base + 5); + case _Base + 6: _LIBCPP_VARIANT_DISPATCH(_Base + 6); + case _Base + 7: _LIBCPP_VARIANT_DISPATCH(_Base + 7); + case _Base + 8: _LIBCPP_VARIANT_DISPATCH(_Base + 8); + case _Base + 9: _LIBCPP_VARIANT_DISPATCH(_Base + 9); + case _Base + 10: _LIBCPP_VARIANT_DISPATCH(_Base + 10); + case _Base + 11: _LIBCPP_VARIANT_DISPATCH(_Base + 11); + case _Base + 12: _LIBCPP_VARIANT_DISPATCH(_Base + 12); + case _Base + 13: _LIBCPP_VARIANT_DISPATCH(_Base + 13); + case _Base + 14: _LIBCPP_VARIANT_DISPATCH(_Base + 14); + case _Base + 15: _LIBCPP_VARIANT_DISPATCH(_Base + 15); + case _Base + 16: _LIBCPP_VARIANT_DISPATCH(_Base + 16); + case _Base + 17: _LIBCPP_VARIANT_DISPATCH(_Base + 17); + case _Base + 18: _LIBCPP_VARIANT_DISPATCH(_Base + 18); + case _Base + 19: _LIBCPP_VARIANT_DISPATCH(_Base + 19); + case _Base + 20: _LIBCPP_VARIANT_DISPATCH(_Base + 20); + case _Base + 21: _LIBCPP_VARIANT_DISPATCH(_Base + 21); + case _Base + 22: _LIBCPP_VARIANT_DISPATCH(_Base + 22); + case _Base + 23: _LIBCPP_VARIANT_DISPATCH(_Base + 23); + case _Base + 24: _LIBCPP_VARIANT_DISPATCH(_Base + 24); + case _Base + 25: _LIBCPP_VARIANT_DISPATCH(_Base + 25); + case _Base + 26: _LIBCPP_VARIANT_DISPATCH(_Base + 26); + case _Base + 27: _LIBCPP_VARIANT_DISPATCH(_Base + 27); + case _Base + 28: _LIBCPP_VARIANT_DISPATCH(_Base + 28); + case _Base + 29: _LIBCPP_VARIANT_DISPATCH(_Base + 29); + case _Base + 30: _LIBCPP_VARIANT_DISPATCH(_Base + 30); + case _Base + 31: _LIBCPP_VARIANT_DISPATCH(_Base + 31); + default: _LIBCPP_VARIANT_DEFAULT(_Base + 32); +#undef _LIBCPP_VARIANT_DEFAULT +#undef _LIBCPP_VARIANT_DISPATCH + } + }(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Vs>(__vs)...); + } + } + template inline _LIBCPP_INLINE_VISIBILITY static constexpr const _Tp& __at(const _Tp& __elem) { return __elem; } @@ -485,42 +621,14 @@ return __result{{_VSTD::forward<_Fs>(__fs)...}}; } - template - struct __dispatcher { - template - inline _LIBCPP_INLINE_VISIBILITY - static constexpr decltype(auto) __dispatch(_Fp __f, _Vs... __vs) { - return __invoke_constexpr( - static_cast<_Fp>(__f), - __access::__base::__get_alt<_Is>(static_cast<_Vs>(__vs))...); - } - }; - template inline _LIBCPP_INLINE_VISIBILITY static constexpr auto __make_dispatch(index_sequence<_Is...>) { - return __dispatcher<_Is...>::template __dispatch<_Fp, _Vs...>; - } - - template - inline _LIBCPP_INLINE_VISIBILITY - static constexpr auto __make_fdiagonal_impl() { - return __make_dispatch<_Fp, _Vs...>( - index_sequence<(__identity<_Vs>{}, _Ip)...>{}); - } - - template - inline _LIBCPP_INLINE_VISIBILITY - static constexpr auto __make_fdiagonal_impl(index_sequence<_Is...>) { - return __base::__make_farray(__make_fdiagonal_impl<_Is, _Fp, _Vs...>()...); - } - - template - inline _LIBCPP_INLINE_VISIBILITY - static constexpr auto __make_fdiagonal() { - constexpr size_t _Np = __uncvref_t<_Vp>::__size(); - static_assert(__all<(_Np == __uncvref_t<_Vs>::__size())...>::value); - return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<_Np>{}); + return +[](_Fp __f, _Vs... __vs) { + return __invoke_constexpr( + static_cast<_Fp>(__f), + __access::__base::__get_alt<_Is>(static_cast<_Vs>(__vs))...); + }; } template @@ -547,13 +655,14 @@ }; struct __variant { - template + template inline _LIBCPP_INLINE_VISIBILITY static constexpr decltype(auto) - __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { + __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vp&& __v, _Wp&& __w) { return __base::__visit_alt_at(__index, _VSTD::forward<_Visitor>(__visitor), - _VSTD::forward<_Vs>(__vs).__impl...); + _VSTD::forward<_Vp>(__v).__impl, + _VSTD::forward<_Wp>(__w).__impl); } template @@ -564,14 +673,15 @@ _VSTD::forward<_Vs>(__vs).__impl...); } - template + template inline _LIBCPP_INLINE_VISIBILITY static constexpr decltype(auto) - __visit_value_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { + __visit_value_at(size_t __index, _Visitor&& __visitor, _Vp&& __v, _Wp&& __w) { return __visit_alt_at( __index, __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)), - _VSTD::forward<_Vs>(__vs)...); + _VSTD::forward<_Vp>(__v), + _VSTD::forward<_Wp>(__w)); } template @@ -585,6 +695,7 @@ private: template + inline _LIBCPP_INLINE_VISIBILITY static constexpr void __std_visit_exhaustive_visitor_check() { static_assert(is_invocable_v<_Visitor, _Values...>, "`std::visit` requires the visitor to be exhaustive."); @@ -787,9 +898,9 @@ template inline _LIBCPP_INLINE_VISIBILITY static _Tp& __construct_alt(__alt<_Ip, _Tp>& __a, _Args&&... __args) { - ::new ((void*)_VSTD::addressof(__a)) + auto* result = ::new ((void*)_VSTD::addressof(__a)) __alt<_Ip, _Tp>(in_place, _VSTD::forward<_Args>(__args)...); - return __a.__value; + return result->__value; } template @@ -1595,11 +1706,8 @@ _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { using __variant_detail::__visitation::__variant; - bool __results[] = {__vs.valueless_by_exception()...}; - for (bool __result : __results) { - if (__result) { - __throw_bad_variant_access(); - } + if ((__vs.valueless_by_exception() || ...)) { + __throw_bad_variant_access(); } return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor), _VSTD::forward<_Vs>(__vs)...);