【问题标题】:SFINAE std::isfinite and similar functions using std::is_arithmeticSFINAE std::isfinite 和使用 std::is_arithmetic 的类似函数
【发布时间】:2014-12-06 21:02:08
【问题描述】:

在将一些代码从 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_arithmetic,所以isfinite 会从重载集中移除。喜欢isnanisfinite的朋友也是如此。所以我的问题是这是否是预期的。

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

我也有点不确定为什么std::is_arithmetic 不是std::is_floating_pointis_arithmetic 不是在整数上暗示isfinite

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

【问题讨论】:

  • 由于 C++11 std::exp 也接受整数类型,而不仅仅是浮点类型。
  • 为了解决您的问题,您可以轻松地为您的班级添加std::is_arithmetic 的专业化。
  • @JoachimPileborg 不,你不能。专用于标准库类型特征(std::common_type 除外)的是 UB。
  • 标准规定应该有三个重载签名分别采用floatdoublelong double。我会提交一个错误。

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


【解决方案1】:

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

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

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

bool isfinite(double x);

bool isfinite(long double x);

此外,应有足够的额外重载以确保:

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

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

【讨论】:

  • 请注意这也适用于 GCC libstdc++
  • @goneskiing 当我tested against libstdc++ 时它工作正常。
  • 我在 Ubuntu 14.10 上使用 GCC 4.9.1(普通 Ubuntu 软件包),命令行“gcc foo.cpp”给出“错误:没有匹配函数调用 'isfinite(Foo&)' 。 ……”。你用的是 4.8 吗,看 cmath 头好像很不一样。
  • 啊 "gcc -std=c++11 foo.cpp" 确实有效。看起来很奇怪,他们没有定义 enable_if,假设没有“-std”选项意味着 c++98,如果你只是做“gcc foo.cpp”
  • 我刚刚发现了针对 libc++ 的错误 llvm.org/bugs/show_bug.cgi?id=18218,它正是在讨论这个问题,所以应该在某个时候修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 2014-03-23
相关资源
最近更新 更多