@@ -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,100 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __throw_if_valueless(_Vs&&... __vs) {
15761580 }
15771581}
15781582
1583+ # define _LIBCPP_VARIANT_DISPATCH_COUNT 11 // Speed up compilation for the common cases
1584+
15791585template < class _Visitor , class ... _Vs, typename >
15801586_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)...);
1587+ using __variant_type = decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()...));
1588+ constexpr size_t __variant_size =
1589+ conditional_t <is_void_v<__variant_type>,
1590+ std::integral_constant<size_t , variant_npos>,
1591+ variant_size<__variant_type>>::value;
1592+ if constexpr (__variant_size <= _LIBCPP_VARIANT_DISPATCH_COUNT) {
1593+ using __variant_detail::__access::__variant;
1594+ # define _LIBCPP_VARIANT_DISPATCH_INDEX (_I ) \
1595+ case _I: \
1596+ if constexpr (_I < __variant_size) { \
1597+ return std::__invoke ( \
1598+ std::forward<_Visitor>(__visitor), __variant::__get_alt<_I>(std::forward<_Vs>(__vs)...).__value ); \
1599+ } \
1600+ [[__fallthrough__]]
1601+ switch ((..., __vs.__variant_type ::index ())) {
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+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1612+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1613+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1614+ static_assert (__LINE__ - _I0 == _LIBCPP_VARIANT_DISPATCH_COUNT, " index count mismatch" );
1615+ default :
1616+ std::__throw_bad_variant_access ();
1617+ }
1618+ # undef _LIBCPP_VARIANT_DISPATCH_INDEX
1619+ } else {
1620+ using __variant_detail::__visitation::__variant;
1621+ std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1622+ return __variant::__visit_value (std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1623+ }
15841624}
15851625
15861626# if _LIBCPP_STD_VER >= 20
15871627template < class _Rp , class _Visitor , class ... _Vs, typename >
15881628_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)...);
1629+ using __variant_type = decltype (std::__upcast_to_variant (std::declval<remove_reference_t <_Vs>*>()...));
1630+ constexpr size_t __variant_size =
1631+ conditional_t <is_void_v<__variant_type>,
1632+ std::integral_constant<size_t , variant_npos>,
1633+ variant_size<__variant_type>>::value;
1634+ if constexpr (__variant_size <= _LIBCPP_VARIANT_DISPATCH_COUNT) {
1635+ using __variant_detail::__access::__variant;
1636+ # define _LIBCPP_VARIANT_DISPATCH_INDEX (_I ) \
1637+ case _I: \
1638+ if constexpr (_I < __variant_size) { \
1639+ if constexpr (std::is_void_v<_Rp>) { \
1640+ std::__invoke ( \
1641+ std::forward<_Visitor>(__visitor), __variant::__get_alt<_I>(std::forward<_Vs>(__vs)...).__value ); \
1642+ break ; \
1643+ } else { \
1644+ return std::__invoke ( \
1645+ std::forward<_Visitor>(__visitor), __variant::__get_alt<_I>(std::forward<_Vs>(__vs)...).__value ); \
1646+ } \
1647+ } \
1648+ [[__fallthrough__]]
1649+ switch ((..., __vs.__variant_type ::index ())) {
1650+ enum : size_t { _I0 = __LINE__ + 1 }; // New line required
1651+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1652+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1653+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1654+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1655+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1656+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1657+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1658+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1659+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1660+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1661+ _LIBCPP_VARIANT_DISPATCH_INDEX (__LINE__ - _I0); // New line required
1662+ static_assert (__LINE__ - _I0 == _LIBCPP_VARIANT_DISPATCH_COUNT, " index count mismatch" );
1663+ default :
1664+ std::__throw_bad_variant_access ();
1665+ }
1666+ # undef _LIBCPP_VARIANT_DISPATCH_INDEX
1667+ } else {
1668+ using __variant_detail::__visitation::__variant;
1669+ std::__throw_if_valueless (std::forward<_Vs>(__vs)...);
1670+ return __variant::__visit_value<_Rp>(std::forward<_Visitor>(__visitor), std::forward<_Vs>(__vs)...);
1671+ }
15921672}
15931673# endif
15941674
1675+ # undef _LIBCPP_VARIANT_DISPATCH_COUNT
1676+
15951677template <class ... _Types>
15961678_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto
15971679swap (variant<_Types...>& __lhs, variant<_Types...>& __rhs) noexcept (noexcept (__lhs.swap(__rhs)))
0 commit comments