@@ -1325,6 +1325,9 @@ private:
13251325 friend struct __variant_detail ::__visitation::__variant;
13261326};
13271327
1328+ template <class ... _Types>
1329+ variant<_Types...> __upcast_to_variant (const volatile variant<_Types...>*);
1330+
13281331template <size_t _Ip, class ... _Types>
13291332_LIBCPP_HIDE_FROM_ABI constexpr bool __holds_alternative (const variant<_Types...>& __v) noexcept {
13301333 return __v.index () == _Ip;
@@ -1578,11 +1581,42 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __throw_if_valueless(_Vs&&... __vs) {
15781581 }
15791582}
15801583
1581- template < class _Visitor , class ... _Vs, typename >
1584+ template <class _Visitor , class ... _Vs, typename >
15821585_LIBCPP_HIDE_FROM_ABI constexpr decltype (auto ) visit(_Visitor&& __visitor, _Vs&&... __vs) {
1583- using __variant_detail::__visitation::__variant;
1584- std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1585- return __variant::__visit_value (std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1586+ # define _XDispatchIndex (_I ) \
1587+ case _I: \
1588+ if constexpr (__variant_size::value > _I) { \
1589+ return __visitor (__variant::__get_alt<_I>(std::forward<_Vs>(__vs)...).__value ); \
1590+ } \
1591+ [[__fallthrough__]]
1592+ # define _XDispatchMax 7 // Speed up compilation for the common cases
1593+ if constexpr (sizeof ...(_Vs) == 1 ) {
1594+ using __variant_size = variant_size<decltype (std::__upcast_to_variant (declval<remove_reference_t <_Vs>*>()...))>;
1595+ if constexpr (__variant_size::value <= _XDispatchMax) {
1596+ using __variant_detail::__access::__variant;
1597+ const size_t __indexes[] = {__vs.index ()...};
1598+ switch (__indexes[0 ]) {
1599+ _XDispatchIndex (_XDispatchMax - 7 );
1600+ _XDispatchIndex (_XDispatchMax - 6 );
1601+ _XDispatchIndex (_XDispatchMax - 5 );
1602+ _XDispatchIndex (_XDispatchMax - 4 );
1603+ _XDispatchIndex (_XDispatchMax - 3 );
1604+ _XDispatchIndex (_XDispatchMax - 2 );
1605+ _XDispatchIndex (_XDispatchMax - 1 );
1606+ _XDispatchIndex (_XDispatchMax - 0 );
1607+ default :
1608+ __throw_bad_variant_access ();
1609+ }
1610+ } else {
1611+ static_assert (__variant_size::value > _XDispatchMax, " forgot to add dispatch case" );
1612+ }
1613+ } else {
1614+ using __variant_detail::__visitation::__variant;
1615+ std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1616+ return __variant::__visit_value (std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1617+ }
1618+ # undef _XDispatchMax
1619+ # undef _XDispatchIndex
15861620}
15871621
15881622# if _LIBCPP_STD_VER >= 20
0 commit comments