The problem I see with this patch is that the expression we use to check for 
convertibility in `__numeric_type` is often very different from the expression 
that actually performs the conversion. The expression that checks for 
convertibility is:
```
    __numeric_test(declval<T>());
```
and the expression that actually converts T is:
```
static_cast<T>(t);
```


First, we are checking for implicit conversions and preforming explicit ones. 
This causes a hard compile error in the following code:
```
struct ImplicitExplicit
{
    operator float() { return 0.0; }
private:
  explicit operator double() { return 0.0; }
};

// Doesn't fire
static_assert(is_same<
    __numeric_type<ImplicitExplicit>::type,float
 >::value, "");

ImplicitExplicit value;
// Fails to compile.
double d = static_cast<double>(value);

// Example in cmath:
std::isless(value, (float)0.0); // Compiles
std::isless(value, (double)0.0); // Doesn't compile.

```

Second, we are checking for conversions with rvalue references and preforming 
conversions with lvalue references. This causes a compile error in the 
following code:
```
struct RValueConvertible
{
    operator double() && { return 0.0; }
};

// Doesn't fire.
static_assert(__numeric_type<RValueConvertible>::value, "");

// Example of error in cmath
RValueConvertible value;
std::isnan(value); // Doesn't compile.
```
Third we copy/move the actual types into the cmath functions before preforming 
the conversion, but we probably shouldn't do this. The following code will not 
compile for this reason
```
struct NonCopyable
{
   NonCopyable() {}
   operator int() { return 1; }
private:
  NonCopyable(NonCopyable const &);
};

static_assert(__numeric_type<NonCopyable>::value, ""); // Doesn't fire

NonCopyable value;
std::isnan(value);
```

I'm not sure these problems should hold this patch up, but I would like to see 
some discussion on it before moving forward.
I think your implementation of std::pow solves each of these problems with a 
substantial increase in code complexity, but I think with some work a cleaner 
solution could be reached.
However it seems that every cmath function will have to perfect forward in 
order to solve all of the problems :(

================
Comment at: include/cmath:944-949
@@ -962,1 +943,8 @@
+pow(_A1&& __lcpp_x, _A2&& __lcpp_y)
+    _NOEXCEPT_
+    (
+        _NOEXCEPT_(__promote<_A1>::__does_not_throw) &&
+        _NOEXCEPT_(__promote<_A2>::__does_not_throw)
+    )
+#endif
 {
----------------
Why does `pow` have the noexcept clause on it anyway?

================
Comment at: include/type_traits:1204-1208
@@ -1201,7 +1203,7 @@
 
 template <>
 struct __numeric_type<void>
 {
-   static const bool value = true;
+    static const bool value = true;
 };
 
----------------
My personal preference would be to use a dummy type instead of  void for this.

http://reviews.llvm.org/D5942



_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to