使用std :: is_arithmetic的SFINAE std :: isfinite和类似函数

时间:2014-12-06 21:02:09

标签: c++ c++11 clang++ libc++

在将一些代码从VS2013移植到GGC 4.9和Clang 3.5(使用libc ++)时,我遇到了编译失败的问题。代码的要点是

#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 );
}

我认为isfinite调用无法编译,因为cmath中的isfinite函数的返回类型声明为:

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

并且由于Foo不是is_arithmeticisfinite会从重载集中删除。 isfinite的朋友isnan也是如此。所以我的问题是这是否是预期的。

标准是否要求isfinite等函数的参数实际上直接doublefloat,而不是隐式转换为它们?

另外,我有点不确定为什么std::is_arithmetic不是std::is_floating_pointis_arithmetic不是isfinite对整数有误?

作为一个额外的问题,指定像 is_convertible_to_floating_point 这样的约束的最佳方法是什么?

1 个答案:

答案 0 :(得分:5)

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

  

分类/比较函数的行为与C相同   具有7.12.3,Classification中定义的相应名称的宏   宏,和7.12.14,C标准中的比较宏。每   函数为三种浮点类型重载,如下所示:

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

bool isfinite(double x);

bool isfinite(long double x);
     

此外,还应有足够的额外过载来确保:

     
      
  1. 如果对应于double参数的任何算术参数具有类型long double,则所有算术参数对应于   double个参数有效地转换为long double
  2.   
  3. 否则,如果对应于double参数的任何算术参数具有类型double或整数类型,则所有算术   对应于double参数的参数被有效地转换为   double
  4.   
  5. 否则,与double参数对应的所有算术参数都具有类型float
  6.   

我提交了一个针对libc ++的错误。