Index: include/cmath =================================================================== --- include/cmath +++ include/cmath @@ -325,7 +325,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type signbit(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_signbit((typename std::__promote<_A1>::type)__lcpp_x); @@ -349,7 +349,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, int>::type +typename std::enable_if::value, int>::type fpclassify(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_fpclassify((typename std::__promote<_A1>::type)__lcpp_x); @@ -373,7 +373,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isfinite(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_isfinite((typename std::__promote<_A1>::type)__lcpp_x); @@ -397,7 +397,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isinf(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_isinf((typename std::__promote<_A1>::type)__lcpp_x); @@ -421,7 +421,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isnan(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_isnan((typename std::__promote<_A1>::type)__lcpp_x); @@ -445,7 +445,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isnormal(_A1 __lcpp_x) _NOEXCEPT { return __libcpp_isnormal((typename std::__promote<_A1>::type)__lcpp_x); @@ -471,8 +471,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -501,8 +500,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -531,8 +529,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -561,8 +558,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -591,8 +587,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -621,8 +616,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2>::value, bool >::type isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT @@ -727,12 +721,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type atan2(_A1 __lcpp_y, _A2 __lcpp_x) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -849,12 +838,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type fmod(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -952,18 +936,25 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type -pow(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT +typename __promote<_A1, _A2>::type +#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES +pow(_A1 __lcpp_x, _A2 __lcpp_y) +#else +pow(_A1&& __lcpp_x, _A2&& __lcpp_y) + _NOEXCEPT_ + ( + _NOEXCEPT_(__promote<_A1>::__does_not_throw) && + _NOEXCEPT_(__promote<_A2>::__does_not_throw) + ) +#endif { - typedef typename __promote<_A1, _A2>::type __result_type; - static_assert((!(is_same<_A1, __result_type>::value && - is_same<_A2, __result_type>::value)), ""); - return pow((__result_type)__lcpp_x, (__result_type)__lcpp_y); + typedef typename __promote<_A1>::type _D1; + typedef typename __promote<_A2>::type _D2; + typedef typename __promote<_D1, _D2>::type type; + static_assert((!(is_same::type, type>::value && + is_same::type, type>::value)), ""); + return pow(static_cast(__promote<_A1>::__apply(_VSTD::forward<_A1>(__lcpp_x))), + static_cast(__promote<_A2>::__apply(_VSTD::forward<_A2>(__lcpp_y)))); } // sin @@ -1114,12 +1105,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1192,12 +1178,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type fdim(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1216,13 +1197,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value && - is_arithmetic<_A3>::value, - __promote<_A1, _A2, _A3> ->::type +typename __promote<_A1, _A2, _A3>::type fma(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT { typedef typename __promote<_A1, _A2, _A3>::type __result_type; @@ -1242,12 +1217,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type fmax(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1266,12 +1236,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type fmin(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1290,12 +1255,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type hypot(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1459,12 +1419,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type nextafter(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1496,12 +1451,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type remainder(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; @@ -1520,12 +1470,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename __lazy_enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - __promote<_A1, _A2> ->::type +typename __promote<_A1, _A2>::type remquo(_A1 __lcpp_x, _A2 __lcpp_y, int* __lcpp_z) _NOEXCEPT { typedef typename __promote<_A1, _A2>::type __result_type; Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -1187,34 +1187,40 @@ #endif // _LIBCPP_HAS_NO_VARIADICS -template +float __numeric_test(float); +double __numeric_test(char); +double __numeric_test(int); +double __numeric_test(unsigned); +double __numeric_test(long); +double __numeric_test(unsigned long); +double __numeric_test(long long); +double __numeric_test(unsigned long long); +double __numeric_test(double); +long double __numeric_test(long double); + +template struct __numeric_type { - static void __test(...); - 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); - static double __test(double); - static long double __test(long double); + static const bool value = false; +}; - typedef decltype(__test(declval<_Tp>())) type; - static const bool value = !is_same::value; +template +struct __numeric_type<_Tp, + typename __void_t()))>::type> +{ + typedef decltype(__numeric_test(declval<_Tp>())) type; + static const bool value = true; }; template <> -struct __numeric_type +struct __numeric_type<__nat> { - static const bool value = true; + static const bool value = true; }; // __promote -template ::value && __numeric_type<_A2>::value && __numeric_type<_A3>::value> @@ -1237,7 +1243,7 @@ }; template -class __promote_imp<_A1, _A2, void, true> +class __promote_imp<_A1, _A2, __nat, true> { private: typedef typename __promote_imp<_A1>::type __type1; @@ -1248,14 +1254,26 @@ }; template -class __promote_imp<_A1, void, void, true> +class __promote_imp<_A1, __nat, __nat, true> { public: typedef typename __numeric_type<_A1>::type type; static const bool value = true; + static const bool __does_not_throw = _NOEXCEPT_OR_FALSE(static_cast(declval<_A1>())); + + static type __apply(float __lcpp_x){ return __lcpp_x; } + static type __apply(char __lcpp_x){ return __lcpp_x; } + static type __apply(int __lcpp_x){ return __lcpp_x; } + static type __apply(unsigned __lcpp_x){ return __lcpp_x; } + static type __apply(long __lcpp_x){ return __lcpp_x; } + static type __apply(unsigned long __lcpp_x){ return __lcpp_x; } + static type __apply(long long __lcpp_x){ return __lcpp_x; } + static type __apply(unsigned long long __lcpp_x){ return __lcpp_x; } + static type __apply(double __lcpp_x){ return __lcpp_x; } + static type __apply(long double __lcpp_x){ return __lcpp_x; } }; -template +template class __promote : public __promote_imp<_A1, _A2, _A3> {}; #ifdef _LIBCPP_STORE_AS_OPTIMIZATION Index: test/std/numerics/c.math/cmath.pass.cpp =================================================================== --- test/std/numerics/c.math/cmath.pass.cpp +++ test/std/numerics/c.math/cmath.pass.cpp @@ -435,15 +435,15 @@ static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); -// static_assert((std::is_same(), (int)0)), double>::value), ""); -// static_assert((std::is_same(), (float)0)), long double>::value), ""); -// static_assert((std::is_same())), float>::value), ""); + static_assert((std::is_same(), (int)0)), double>::value), ""); + static_assert((std::is_same(), (float)0)), long double>::value), ""); + static_assert((std::is_same())), float>::value), ""); static_assert((std::is_same::value), ""); assert(std::pow(1,1) == 1); -// assert(std::pow(Value(), Value()) == 1); -// assert(std::pow(1.0f, Value()) == 1); -// assert(std::pow(1.0, Value()) == 1); -// assert(std::pow(Value(), 1LL) == 1); + assert(std::pow(Value(), Value()) == 1); + assert(std::pow(1.0f, Value()) == 1); + assert(std::pow(1.0, Value()) == 1); + assert(std::pow(Value(), 1LL) == 1); } void test_sin()