constexpr vs编译时数学函数的模板?

Vin*_*ent 8 c++ templates metaprogramming constexpr c++11

我对C++ 2011的新关键字constexpr很困惑.我想知道在编写时间函数(特别是数学函数)时,在哪里使用constexpr以及在哪里使用模板元编程.例如,如果我们采用整数pow函数:

// 1 : 
template <int N> inline double tpow(double x)
{
    return x*tpow<N-1>(x);
}
template <> inline double tpow<0>(double x)
{
    return 1.0;
}

// 2 :
constexpr double cpow(double x, int N)
{
    return (N>0) ? (x*cpow(x, N-1)) : (1.0);
}

// 3 :
template <int N> constexpr double tcpow(double x)
{
    return x*tcpow<N-1>(x);
}
template <> constexpr double tcpow<0>(double x)
{
    return 1.0;
}
Run Code Online (Sandbox Code Playgroud)

第2和第3功能是否相同?什么是最好的解决方案?它是否产生相同的结果:

  • 如果x在编译时已知
  • 如果在编译时不知道x

何时使用constexpr以及何时使用模板元编程?

编辑1:修改代码以包括模板的专业化

std*_*ave 8

我最近可能不应该回答模板元编程问题.但是,我走了.

首先,constexpr未在Visual Studio 2012中实现.如果您想为Windows开发,请忘记它.我知道,它很糟糕,我讨厌微软不包括它.

除此之外,还有许多事情你可以声明为常量,但就"你可以在编译时使用它们"而言,它们并不是真正的"常量".例如:

const int foo[5] = { 2, 5, 1, 9, 4 };
const int bar = foo[foo[2]]; // Fail!
Run Code Online (Sandbox Code Playgroud)

你认为你可以在编译时读取它,对吗?不.但是你可以把它变成一个constexpr.

constexpr int foo[5] = { 2, 5, 1, 9, 4 };
constexpr int bar = foo[foo[2]]; // Woohoo!
Run Code Online (Sandbox Code Playgroud)

Constexpr非常适合"恒定传播"优化.这意味着如果你有一个变量X,它是在编译时基于某些条件(也许是元编程)声明的,如果它是constexpr那么编译器知道它可以"安全地"使用它来进行优化,比如说,删除指令如a =(X*y); 并用a = 0替换它们; 如果X评估为0(并且满足其他条件).

显然这很好,因为对于许多数学函数,恒定传播可以为您提供简单(使用)的过早优化.

它们的主要用途,除了相当深奥的东西(比如让我更容易编写编译时字节码解释器),就是能够制作可以在编译时调用和使用的"函数"或类.时间和运行时间.

基本上它们只是填补了C++ 03中的一个漏洞并帮助编译器进行优化.

那么你的哪3个是"最好的"?

2可以在运行时调用,而其他只是编译时.那太好了.

还有一点.维基百科为您提供了"constexpr允许此项"的基本摘要,但模板元编程可能很复杂.Constexpr使部分内容变得更加容易.我希望我有一个明确的例子,除了说,从数组中读取.

我想,一个好的数学例子是,如果你想实现一个用户定义的复数类.仅使用模板元编程而不使用constexpr进行编码将会更复杂一个数量级.

那么什么时候不应该使用constexpr?老实说,constexpr基本上是"const,除了更多CONST".您通常可以在任何使用const的地方使用它,但有一些注意事项,例如在运行时调用时,如果函数的输入不是const,则函数将执行非const.

嗯.好的,这就是现在.我太过于过分而无法说出更多.我希望我有所帮助,如果我没有,请随时向我投票,我会删除它.

  • `2可以在运行时调用,而其他只是编译时.-这是不正确的.可以在运行时调用所有函数.在编译时,只计算递归的深度,并且对于第1和第3,N应该是constexpr.对于2nd - N可以是运行时. (2认同)