Index: include/cmath
===================================================================
--- include/cmath	(revision 198166)
+++ include/cmath	(working copy)
@@ -937,9 +937,10 @@
 inline _LIBCPP_INLINE_VISIBILITY long double modf(long double __x, long double* __y) _NOEXCEPT {return modfl(__x, __y);}
 #endif
 
+#endif // __sun__ 
+
 // pow
 
-#endif // __sun__ 
 using ::pow;
 using ::powf;
 
@@ -952,21 +953,33 @@
 
 template <class _A1, class _A2>
 inline _LIBCPP_INLINE_VISIBILITY
-typename enable_if
-<
-    is_arithmetic<_A1>::value &&
-    is_arithmetic<_A2>::value,
-    typename __promote<_A1, _A2>::type
->::type
-pow(_A1 __x, _A2 __y) _NOEXCEPT
+typename std::enable_if<
+    !std::is_same<typename std::__numeric_type<_A1>::type, void>::value &&
+    !std::is_same<typename std::__numeric_type<_A2>::type, void>::value, 
+    typename _VSTD::__promote<
+        typename std::__numeric_type<_A1>::type,
+        typename std::__numeric_type<_A2>::type
+        >::type
+    >::type
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+pow(_A1 __x, _A2 __y)
+#else
+pow(_A1 &&__x, _A2 &&__y)
+#endif
+ _NOEXCEPT_ (
+ 			   _NOEXCEPT_((std::forward<_A1>(__x)))
+			&& _NOEXCEPT_((std::forward<_A2>(__y)))
+            && _NOEXCEPT_((typename std::__numeric_type<_A1>::type)(__x))
+			&& _NOEXCEPT_((typename std::__numeric_type<_A2>::type)(__y))
+			)
 {
-    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)__x, (__result_type)__y);
+    typedef typename std::__numeric_type<_A1>::type _D1;
+    typedef typename std::__numeric_type<_A1>::type _D2;
+    typedef typename _VSTD::__promote<_D1, _D2>::type type;
+    static_assert((!(std::is_same<_A1, type>::value && std::is_same<_A2, type>::value)), "" );
+    return pow((type) ((_D1) __x), (type) ((_D2) __y)); 
 }
 
-
 // sin
 
 using ::sin;
Index: include/type_traits
===================================================================
--- include/type_traits	(revision 198166)
+++ include/type_traits	(working copy)
@@ -1151,6 +1151,38 @@
 
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 
+// __numeric_type
+
+template <class _A1>
+struct __numeric_type_imp
+{
+   static void __test(...);
+
+   static float       __test(float);
+   static double      __test(double);
+   static long double __test(long double);
+
+   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);
+
+   typedef decltype(__test(_VSTD::declval<_A1>())) type;
+};
+
+struct __numeric_type_nothing {};
+
+template <class _A1>
+struct __numeric_type : public std::conditional<
+    std::is_same<typename __numeric_type_imp<_A1>::type,void>::value,
+	__numeric_type_nothing,
+	__numeric_type_imp<_A1>
+	>::type
+{};
+
 // __promote
 
 template <class _A1, class _A2 = void, class _A3 = void,
Index: test/numerics/c.math/cmath.pass.cpp
===================================================================
--- test/numerics/c.math/cmath.pass.cpp	(revision 198166)
+++ test/numerics/c.math/cmath.pass.cpp	(working copy)
@@ -15,6 +15,12 @@
 
 #include "hexfloat.h"
 
+// convertible to int/float/double/etc
+template <class T, int N=0>
+struct Value {
+    operator T () { return T(N); }
+};
+
 void test_abs()
 {
     static_assert((std::is_same<decltype(std::abs((float)0)), float>::value), "");
@@ -333,7 +339,14 @@
     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), "");
     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);
 }
 
 void test_sin()
