@@ -1323,6 +1323,10 @@ private:
13231323 friend struct __variant_detail ::__visitation::__variant;
13241324};
13251325
1326+ template <class ... _Types>
1327+ variant<_Types...> __upcast_to_variant (const volatile variant<_Types...>*);
1328+ void __upcast_to_variant (...);
1329+
13261330template <size_t _Ip, class ... _Types>
13271331_LIBCPP_HIDE_FROM_ABI constexpr bool __holds_alternative (const variant<_Types...>& __v) noexcept {
13281332 return __v.index () == _Ip;
@@ -1576,22 +1580,81 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __throw_if_valueless(_Vs&&... __vs) {
15761580 }
15771581}
15781582
1583+ # define _LIBCPP_VARIANT_DISPATCH_COUNT 8 // Speed up compilation for the common cases
1584+ # define _LIBCPP_VARIANT_DISPATCH_INDEX (_I ) \
1585+ case _I: \
1586+ if constexpr (__variant_size::value > _I) { \
1587+ return std::__invoke (std::forward<_Visitor>(__visitor), __variant::__get_alt<_I>(std::forward<_Vs>(__vs)...).__value ); \
1588+ } \
1589+ [[__fallthrough__]]
1590+
15791591template < class _Visitor , class ... _Vs, typename >
15801592_LIBCPP_HIDE_FROM_ABI constexpr decltype (auto ) visit(_Visitor&& __visitor, _Vs&&... __vs) {
1581- using __variant_detail::__visitation::__variant;
1582- std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1583- return __variant::__visit_value (std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1593+ using __variant_size = variant_size<decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()...))>;
1594+ if constexpr (sizeof ...(_Vs) == 1 &&
1595+ conditional_t <is_same_v<variant_size<void >, __variant_size>,
1596+ std::integral_constant<size_t , variant_npos>,
1597+ __variant_size>::value < _LIBCPP_VARIANT_DISPATCH_COUNT) {
1598+ using __variant_detail::__access::__variant;
1599+ const size_t __indices[] = {
1600+ __vs.decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()))::index ()...};
1601+ switch (__indices[0 ]) {
1602+ enum : size_t { _I0 = __LINE__ + 1 }; // New line required
1603+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1604+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1605+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1606+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1607+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1608+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1609+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1610+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1611+ static_assert (__LINE__ - _I0 == _LIBCPP_VARIANT_DISPATCH_COUNT, " index count mismatch" );
1612+ default :
1613+ std::__throw_bad_variant_access ();
1614+ }
1615+ } else {
1616+ using __variant_detail::__visitation::__variant;
1617+ std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1618+ return __variant::__visit_value (std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1619+ }
15841620}
15851621
15861622# if _LIBCPP_STD_VER >= 20
15871623template < class _Rp , class _Visitor , class ... _Vs, typename >
15881624_LIBCPP_HIDE_FROM_ABI constexpr _Rp visit (_Visitor&& __visitor, _Vs&&... __vs) {
1589- using __variant_detail::__visitation::__variant;
1590- std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1591- return __variant::__visit_value<_Rp>(std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1625+ using __variant_size = variant_size<decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()...))>;
1626+ if constexpr (sizeof ...(_Vs) == 1 &&
1627+ conditional_t <is_same_v<variant_size<void >, __variant_size>,
1628+ std::integral_constant<size_t , variant_npos>,
1629+ __variant_size>::value < _LIBCPP_VARIANT_DISPATCH_COUNT) {
1630+ using __variant_detail::__access::__variant;
1631+ const size_t __indices[] = {
1632+ __vs.decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()))::index ()...};
1633+ switch (__indices[0 ]) {
1634+ enum : size_t { _I0 = __LINE__ + 1 }; // New line required
1635+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1636+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1637+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1638+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1639+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1640+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1641+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1642+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1643+ static_assert (__LINE__ - _I0 == _LIBCPP_VARIANT_DISPATCH_COUNT, " index count mismatch" );
1644+ default :
1645+ std::__throw_bad_variant_access ();
1646+ }
1647+ } else {
1648+ using __variant_detail::__visitation::__variant;
1649+ std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1650+ return __variant::__visit_value<_Rp>(std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1651+ }
15921652}
15931653# endif
15941654
1655+ # undef _LIBCPP_VARIANT_DISPATCH_INDEX
1656+ # undef _LIBCPP_VARIANT_DISPATCH_COUNT
1657+
15951658template <class ... _Types>
15961659_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto
15971660swap (variant<_Types...>& __lhs, variant<_Types...>& __rhs) noexcept (noexcept (__lhs.swap(__rhs)))
0 commit comments