9

在 C++ 03 中,使用 egstd::pow(double_val, 6)比使用std::pow(double_val, 6.0).

使用 C++11 编译时不再是这种情况。查看 gcc 的 libstdc++-4.8 中的 cmath 标头,可以看到显式 pow(double, int) 不再存在,这种情况由以下模板处理,该模板将 int 提升为 double:

template<typename _Tp, typename _Up>
inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
pow(_Tp __x, _Up __y) {
  typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
  return std::pow(__type(__x), __type(__y));
}

这是 C++11 标准中的行为还是未来的 libstdc++ 实现会返回到更快的方法?

其次,如果出于标准或实施原因,更快的行为不再可能,那么再次实现它的最便携的方法是什么?我power(...)在“ext/numeric”下的 gcc stdlibc++ 中看到了一个函数,但这被标记为非标准SGI(rip) 扩展。

4

2 回答 2

4

首先,是的,这种行为符合 C++11 标准(尽管与 C++03 不同),在第 26.8 节第 11 段中说:

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

  1. 如果对应于 double 形参的任何实参的类型为 long double,则对应于 double 形参的所有实参都将有效地转换为 long double。

  2. 否则,如果对应于 double 参数的任何实参具有 double 类型或整数类型,则对应于 double 形参的所有实参都将有效地转换为 double。

  3. 否则,对应于双参数的所有参数都被有效地转换为浮点数。

(除了float-only、double-only 和long double-only 的重载。)

所以实现实际上必须将该整数参数转换为 adouble并且我认为符合标准的库不可能为std::pow整数幂提供更快的速度,除了可能检查double参数的完整性(这是一个词吗?)和在这种情况下使用特殊路径。

为了提供一种独立于平台的更快方式,我想到的唯一一件事就是编写一个自定义包装器,power如果它存在的话,它会委托给这个非标准。std::pow除此之外,我不知道如何在不编写自己的实现的情况下再次注入这种行为。

编辑:然而,当查看这个答案时,只要它的行为与std::pow(double(x), double(y)). 因此,有一种实现提供更快版本的可能性,但我不会像您在 C++03 中所做的那样依赖它(恕我直言,它甚至是标准的一部分,但我可能错了) .

于 2013-09-18T14:05:20.003 回答
2

C 只提供double pow(double, double)重载(回想一下,C 无论如何都不允许函数重载)。C++11 标准 (26.8/9) 表示将以下重载(除了 C 之外)添加到 namespace std

float pow(float, float);
long double pow(long double, long double);

因此,double pow(double, int)是扩展而不是标准功能。因此,实现可能会提供它,也可能不提供。

在 Christian Rau 评论和回答之后编辑。

现在我相信过载一定存在。因此,应该有一个double pow(double, int)过载。但是,这种重载必须(正如他在回答中所说)将intadouble和 call强制转换为double pow(double, double)

实际上有很多超载。提供它们的最简单方法不是作为普通函数,而是作为模板函数,与 OP 中显示的 libstdc++ 实现完全相同。

另请参阅Howard Hinnant 解释详细信息的未解决问题。

最后,Hulk 提供的链接非常相​​关,Howard Hinnant(再次)解释说,几乎没有理由提供一个优化的重载来做任何不同于intdouble.

于 2013-09-18T13:20:44.970 回答