Addressed review comments. Keep in mind that only `pow` is implemented 
completely, once we get that one right I'll update the others to follow.


http://reviews.llvm.org/D5942

Files:
  include/cmath
  include/type_traits
  test/std/numerics/c.math/cmath.pass.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/cmath
===================================================================
--- include/cmath
+++ include/cmath
@@ -325,7 +325,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
 signbit(_A1 __lcpp_x) _NOEXCEPT
 {
     return __libcpp_signbit((typename std::__promote<_A1>::type)__lcpp_x);
@@ -349,7 +349,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, int>::type
+typename std::enable_if<std::__promote<_A1>::value, int>::type
 fpclassify(_A1 __lcpp_x) _NOEXCEPT
 {
     return __libcpp_fpclassify((typename std::__promote<_A1>::type)__lcpp_x);
@@ -373,7 +373,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
 isfinite(_A1 __lcpp_x) _NOEXCEPT
 {
     return __libcpp_isfinite((typename std::__promote<_A1>::type)__lcpp_x);
@@ -397,7 +397,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
 isinf(_A1 __lcpp_x) _NOEXCEPT
 {
     return __libcpp_isinf((typename std::__promote<_A1>::type)__lcpp_x);
@@ -421,7 +421,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
 isnan(_A1 __lcpp_x) _NOEXCEPT
 {
     return __libcpp_isnan((typename std::__promote<_A1>::type)__lcpp_x);
@@ -445,7 +445,7 @@
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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<typename remove_reference<_A1>::type, type>::value &&
+                     is_same<typename remove_reference<_A2>::type, type>::value)), "");
+    return pow(static_cast<type>(__promote<_A1>::__apply(_VSTD::forward<_A1>(__lcpp_x))),
+               static_cast<type>(__promote<_A2>::__apply(_VSTD::forward<_A2>(__lcpp_y))));
 }
 
 // sin
@@ -1114,12 +1105,7 @@
 
 template <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2, class _A3>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _A1, class _A2>
 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 <class _Tp>
+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 <class _Tp, class = void>
 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<type, void>::value;
+template <class _Tp>
+struct __numeric_type<_Tp, 
+    typename __void_t<decltype(__numeric_test(declval<_Tp>()))>::type>
+{
+    typedef decltype(__numeric_test(declval<_Tp>())) type;
+    static const bool value = true;
 };
 
 template <>
-struct __numeric_type<void>
+struct __numeric_type<__nat>
 {
-   static const bool value = true;
+    static const bool value = true;
 };
 
 // __promote
 
-template <class _A1, class _A2 = void, class _A3 = void,
+template <class _A1, class _A2 = __nat, class _A3 = __nat,
           bool = __numeric_type<_A1>::value &&
                  __numeric_type<_A2>::value &&
                  __numeric_type<_A3>::value>
@@ -1237,7 +1243,7 @@
 };
 
 template <class _A1, class _A2>
-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 _A1>
-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<type>(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 <class _A1, class _A2 = void, class _A3 = void>
+template <class _A1, class _A2 = __nat, class _A3 = __nat>
 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<decltype(std::powf(0,0)), float>::value), "");
     static_assert((std::is_same<decltype(std::powl(0,0)), long double>::value), "");
     static_assert((std::is_same<decltype(std::pow((int)0, (int)0)), double>::value), "");
-//     static_assert((std::is_same<decltype(std::pow(Value<int>(), (int)0)), double>::value), "");
-//     static_assert((std::is_same<decltype(std::pow(Value<long double>(), (float)0)), long double>::value), "");
-//     static_assert((std::is_same<decltype(std::pow((float) 0, Value<float>())), float>::value), "");
+    static_assert((std::is_same<decltype(std::pow(Value<int>(), (int)0)), double>::value), "");
+    static_assert((std::is_same<decltype(std::pow(Value<long double>(), (float)0)), long double>::value), "");
+    static_assert((std::is_same<decltype(std::pow((float) 0, Value<float>())), float>::value), "");
     static_assert((std::is_same<decltype(pow(Ambiguous(), Ambiguous())), Ambiguous>::value), "");
     assert(std::pow(1,1) == 1);
-//     assert(std::pow(Value<int,1>(), Value<float,1>())  == 1);
-//     assert(std::pow(1.0f, Value<double,1>()) == 1);
-//     assert(std::pow(1.0, Value<int,1>()) == 1);
-//     assert(std::pow(Value<long double,1>(), 1LL) == 1);
+    assert(std::pow(Value<int,1>(), Value<float,1>())  == 1);
+    assert(std::pow(1.0f, Value<double,1>()) == 1);
+    assert(std::pow(1.0, Value<int,1>()) == 1);
+    assert(std::pow(Value<long double,1>(), 1LL) == 1);
 }
 
 void test_sin()
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to