Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFINAE std::isfinite and similar functions using std::is_arithmetic

I just ran into a compilation failure when porting some code from VS2013 to GGC 4.9 and Clang 3.5 ( using libc++ ). The gist of the code is

#include <cmath>

struct Foo
{
    operator double() const { return( 101.0 ); } // Implicit conversion to double
};

int main( int, char** )
{
    Foo foo;

    std::exp( foo );      // Compiles
    std::isfinite( foo ); // Does not

    return( 0 );
}

I believe the isfinite call does not compile because the isfinite funtion in cmath has return type declared as:

typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type

and because Foo is not is_arithmetic, isfinite gets removed from the overload set. The same is true of friends of isfinite like isnan. So my question is whether this is expected.

Does the standard require that arguments to functions like isfinite as actually directly double or float as opposed to being implicitly convertible to them?

Also I'm a bit unsure why is std::is_arithmetic not std::is_floating_point, doesn't is_arithmetic imply isfinite on integers?

As an extra question what is the best way of specifying a constraint like is_convertible_to_floating_point?

like image 636
goneskiing Avatar asked Dec 06 '14 21:12

goneskiing


1 Answers

§26.8 [c.math]/p10-11:

The classification/comparison functions behave the same as the C macros with the corresponding names defined in 7.12.3, Classification macros, and 7.12.14, Comparison macros in the C Standard. Each function is overloaded for the three floating-point types, as follows:

// other functions omitted
bool isfinite(float x);

bool isfinite(double x);

bool isfinite(long double x);

Moreover, there shall be additional overloads sufficient to ensure:

  1. If any arithmetic argument corresponding to a double parameter has type long double, then all arithmetic arguments corresponding to double parameters are effectively cast to long double.
  2. Otherwise, if any arithmetic argument corresponding to a double parameter has type double or an integer type, then all arithmetic arguments corresponding to double parameters are effectively cast to double.
  3. Otherwise, all arithmetic arguments corresponding to double parameters have type float.

I'd file a bug against libc++.

like image 180
T.C. Avatar answered Oct 14 '22 10:10

T.C.