From 948bffa951cf143da5f4caa461b25ce76fa137d0 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Thu, 8 May 2025 22:48:57 +0200 Subject: [PATCH] [libc++] Simplify __promote (#136101) This avoids instantiating an extra class for every variant `__promote` is used in. --- libcxx/include/__math/copysign.h | 2 +- libcxx/include/__math/exponential_functions.h | 4 +-- libcxx/include/__math/fdim.h | 4 +-- libcxx/include/__math/fma.h | 4 +-- libcxx/include/__math/hypot.h | 8 ++--- .../__math/inverse_trigonometric_functions.h | 4 +-- libcxx/include/__math/min_max.h | 8 ++--- libcxx/include/__math/modulo.h | 4 +-- libcxx/include/__math/remainder.h | 8 ++--- libcxx/include/__math/rounding_functions.h | 4 +-- libcxx/include/__math/traits.h | 12 +++---- libcxx/include/__type_traits/promote.h | 36 +++++++++---------- libcxx/include/cmath | 8 ++--- libcxx/include/complex | 13 ++++--- .../complex.number/cmplx.over.pow.pass.cpp | 6 ++-- 15 files changed, 59 insertions(+), 66 deletions(-) diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h index c3ca6a3b0370..4c297cb0894e 100644 --- a/libcxx/include/__math/copysign.h +++ b/libcxx/include/__math/copysign.h @@ -33,7 +33,7 @@ namespace __math { } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> copysign(_A1 __x, _A2 __y) _NOEXCEPT { return ::__builtin_copysign(__x, __y); } diff --git a/libcxx/include/__math/exponential_functions.h b/libcxx/include/__math/exponential_functions.h index 109c3349970f..09930b7819e2 100644 --- a/libcxx/include/__math/exponential_functions.h +++ b/libcxx/include/__math/exponential_functions.h @@ -158,8 +158,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double pow(long double __x, long double __y) _ } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type pow(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> pow(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::pow((__result_type)__x, (__result_type)__y); } diff --git a/libcxx/include/__math/fdim.h b/libcxx/include/__math/fdim.h index dc1b4ecc07dc..a1081c7bde3d 100644 --- a/libcxx/include/__math/fdim.h +++ b/libcxx/include/__math/fdim.h @@ -35,8 +35,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double fdim(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fdim(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fdim(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fdim((__result_type)__x, (__result_type)__y); } diff --git a/libcxx/include/__math/fma.h b/libcxx/include/__math/fma.h index 6ba7a5a2d26d..b972d85b89cb 100644 --- a/libcxx/include/__math/fma.h +++ b/libcxx/include/__math/fma.h @@ -40,8 +40,8 @@ template ::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2, _A3>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2, _A3> fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2, _A3>; static_assert( !(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && _IsSame<_A3, __result_type>::value), ""); diff --git a/libcxx/include/__math/hypot.h b/libcxx/include/__math/hypot.h index b2bf8e11c8ec..8e8c35b4a41c 100644 --- a/libcxx/include/__math/hypot.h +++ b/libcxx/include/__math/hypot.h @@ -43,8 +43,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type hypot(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> hypot(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::hypot((__result_type)__x, (__result_type)__y); } @@ -91,8 +91,8 @@ template && is_arithmetic_v<_A2> && is_arithmetic_v<_A3>, int> = 0 > -_LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2, _A3>::type; +_LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2, _A3> hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2, _A3>; static_assert(!( std::is_same_v<_A1, __result_type> && std::is_same_v<_A2, __result_type> && std::is_same_v<_A3, __result_type>)); return __math::__hypot( diff --git a/libcxx/include/__math/inverse_trigonometric_functions.h b/libcxx/include/__math/inverse_trigonometric_functions.h index cd98b46a6aab..409500278e7a 100644 --- a/libcxx/include/__math/inverse_trigonometric_functions.h +++ b/libcxx/include/__math/inverse_trigonometric_functions.h @@ -86,8 +86,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double atan2(long double __y, long double __x) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type atan2(_A1 __y, _A2 __x) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> atan2(_A1 __y, _A2 __x) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::atan2((__result_type)__y, (__result_type)__x); } diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h index db900c849e72..1ddbb557d1e8 100644 --- a/libcxx/include/__math/min_max.h +++ b/libcxx/include/__math/min_max.h @@ -39,8 +39,8 @@ template } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmax(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmax((__result_type)__x, (__result_type)__y); } @@ -61,8 +61,8 @@ template } template ::value && is_arithmetic<_A2>::value, int> = 0> -[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmin(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmin((__result_type)__x, (__result_type)__y); } diff --git a/libcxx/include/__math/modulo.h b/libcxx/include/__math/modulo.h index c8ea506f37d7..71405abb6b9b 100644 --- a/libcxx/include/__math/modulo.h +++ b/libcxx/include/__math/modulo.h @@ -37,8 +37,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double fmod(long double __x, long double __y) } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmod(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> fmod(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmod((__result_type)__x, (__result_type)__y); } diff --git a/libcxx/include/__math/remainder.h b/libcxx/include/__math/remainder.h index 0adb7f3af5de..39fb76af6bde 100644 --- a/libcxx/include/__math/remainder.h +++ b/libcxx/include/__math/remainder.h @@ -37,8 +37,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double remainder(long double __x, long double } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remainder(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> remainder(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remainder((__result_type)__x, (__result_type)__y); } @@ -59,8 +59,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double remquo(long double __x, long double __y } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remquo((__result_type)__x, (__result_type)__y, __z); } diff --git a/libcxx/include/__math/rounding_functions.h b/libcxx/include/__math/rounding_functions.h index 474f585a62f1..aadeb395fa2e 100644 --- a/libcxx/include/__math/rounding_functions.h +++ b/libcxx/include/__math/rounding_functions.h @@ -158,8 +158,8 @@ inline _LIBCPP_HIDE_FROM_ABI long double nextafter(long double __x, long double } template ::value && is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type nextafter(_A1 __x, _A2 __y) _NOEXCEPT { - using __result_type = typename __promote<_A1, _A2>::type; +inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> nextafter(_A1 __x, _A2 __y) _NOEXCEPT { + using __result_type = __promote_t<_A1, _A2>; static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::nextafter((__result_type)__x, (__result_type)__y); } diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 550eb393e2d4..4a6e58c6da8a 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -145,7 +145,7 @@ template ::value, int> = 0> template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isgreater((type)__x, (type)__y); } @@ -153,7 +153,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -161,7 +161,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isless((type)__x, (type)__y); } @@ -169,7 +169,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_islessequal((type)__x, (type)__y); } @@ -177,7 +177,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_islessgreater((type)__x, (type)__y); } @@ -185,7 +185,7 @@ template ::value && is_ar template ::value && is_arithmetic<_A2>::value, int> = 0> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { - using type = typename __promote<_A1, _A2>::type; + using type = __promote_t<_A1, _A2>; return __builtin_isunordered((type)__x, (type)__y); } diff --git a/libcxx/include/__type_traits/promote.h b/libcxx/include/__type_traits/promote.h index b449a749004a..96b4903032b1 100644 --- a/libcxx/include/__type_traits/promote.h +++ b/libcxx/include/__type_traits/promote.h @@ -10,7 +10,7 @@ #define _LIBCPP___TYPE_TRAITS_PROMOTE_H #include <__config> -#include <__type_traits/integral_constant.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_arithmetic.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -19,28 +19,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -class __promote { - static_assert((is_arithmetic<_Args>::value && ...)); - - static float __test(float); - static double __test(char); - static double __test(int); - static double __test(unsigned); - static double __test(long); - static double __test(unsigned long); - static double __test(long long); - static double __test(unsigned long long); +float __promote_impl(float); +double __promote_impl(char); +double __promote_impl(int); +double __promote_impl(unsigned); +double __promote_impl(long); +double __promote_impl(unsigned long); +double __promote_impl(long long); +double __promote_impl(unsigned long long); #if _LIBCPP_HAS_INT128 - static double __test(__int128_t); - static double __test(__uint128_t); +double __promote_impl(__int128_t); +double __promote_impl(__uint128_t); #endif - static double __test(double); - static long double __test(long double); +double __promote_impl(double); +long double __promote_impl(long double); -public: - using type = decltype((__test(_Args()) + ...)); -}; +template +using __promote_t _LIBCPP_NODEBUG = + decltype((__enable_if_t<(is_arithmetic<_Args>::value && ...)>)0, (std::__promote_impl(_Args()) + ...)); _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/cmath b/libcxx/include/cmath index 9cf044d4d023..bee743f702d0 100644 --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -599,11 +599,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr long double lerp(long double __a, long do } template -inline _LIBCPP_HIDE_FROM_ABI constexpr - typename enable_if_t< is_arithmetic<_A1>::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value, - __promote<_A1, _A2, _A3> >::type - lerp(_A1 __a, _A2 __b, _A3 __t) noexcept { - typedef typename __promote<_A1, _A2, _A3>::type __result_type; + requires(is_arithmetic_v<_A1> && is_arithmetic_v<_A2> && is_arithmetic_v<_A3>) +_LIBCPP_HIDE_FROM_ABI inline constexpr __promote_t<_A1, _A2, _A3> lerp(_A1 __a, _A2 __b, _A3 __t) noexcept { + using __result_type = __promote_t<_A1, _A2, _A3>; static_assert(!( _IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && _IsSame<_A3, __result_type>::value)); return std::__lerp((__result_type)__a, (__result_type)__b, (__result_type)__t); diff --git a/libcxx/include/complex b/libcxx/include/complex index fda75796ffa6..e9baec04d946 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -1101,21 +1101,20 @@ inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const com } template ::value && is_floating_point<_Up>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI complex::type> -pow(const complex<_Tp>& __x, const complex<_Up>& __y) { - typedef complex::type> result_type; +inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const complex<_Tp>& __x, const complex<_Up>& __y) { + typedef complex<__promote_t<_Tp, _Up> > result_type; return std::pow(result_type(__x), result_type(__y)); } template ::value && is_arithmetic<_Up>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI complex::type> pow(const complex<_Tp>& __x, const _Up& __y) { - typedef complex::type> result_type; +inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const complex<_Tp>& __x, const _Up& __y) { + typedef complex<__promote_t<_Tp, _Up> > result_type; return std::pow(result_type(__x), result_type(__y)); } template ::value && is_floating_point<_Up>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI complex::type> pow(const _Tp& __x, const complex<_Up>& __y) { - typedef complex::type> result_type; +inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const _Tp& __x, const complex<_Up>& __y) { + typedef complex<__promote_t<_Tp, _Up> > result_type; return std::pow(result_type(__x), result_type(__y)); } diff --git a/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp b/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp index 8c1b3a17c669..d87e259cefe3 100644 --- a/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp +++ b/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp @@ -10,9 +10,9 @@ // XFAIL: FROZEN-CXX03-HEADERS-FIXME -// template complex<__promote::type> pow(const complex&, const U&); -// template complex<__promote::type> pow(const complex&, const complex&); -// template complex<__promote::type> pow(const T&, const complex&); +// template complex<__promote_t> pow(const complex&, const U&); +// template complex<__promote_t> pow(const complex&, const complex&); +// template complex<__promote_t> pow(const T&, const complex&); // Test that these additional overloads are free from catching std::complex, // which is expected by several 3rd party libraries, see https://github.com/llvm/llvm-project/issues/109858.