在我看来,拥有一个“总是返回5的函数”破坏或稀释了“调用函数”的意义。必须有一个原因,或者需要这个功能,否则它就不会出现在c++ 11中。为什么会在那里?

// preprocessor.
#define MEANING_OF_LIFE 42

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

在我看来,如果我写一个函数,返回一个字面值,然后我进行代码检查,有人会告诉我,我应该声明一个常量值,而不是返回5。


当前回答

Stroustrup在“Going Native 2012”大会上的演讲如下:

template<int M, int K, int S> struct Unit { // a unit in the MKS system
       enum { m=M, kg=K, s=S };
};

template<typename Unit> // a magnitude with a unit 
struct Value {
       double val;   // the magnitude 
       explicit Value(double d) : val(d) {} // construct a Value from a double 
};

using Speed = Value<Unit<1,0,-1>>;  // meters/second type
using Acceleration = Value<Unit<1,0,-2>>;  // meters/second/second type
using Second = Unit<0,0,1>;  // unit: sec
using Second2 = Unit<0,0,2>; // unit: second*second 

constexpr Value<Second> operator"" s(long double d)
   // a f-p literal suffixed by ‘s’
{
  return Value<Second> (d);  
}   

constexpr Value<Second2> operator"" s2(long double d)
  // a f-p literal  suffixed by ‘s2’ 
{
  return Value<Second2> (d); 
}

Speed sp1 = 100m/9.8s; // very fast for a human 
Speed sp2 = 100m/9.8s2; // error (m/s2 is acceleration)  
Speed sp3 = 100/9.8s; // error (speed is m/s and 100 has no unit) 
Acceleration acc = sp1/0.5s; // too fast for a human

其他回答

何时使用constexpr:

只要有编译时间常数。

这里的许多回答似乎有些相反,或者把安静的部分大声说出来,把吵闹的部分小声说出来。关于constexpr你需要知道的一件关键的事情是:

// This guarantees only that the value of "MeaningOfLife" can not be changed
// from the value calculated on this line by "complex_initialization()"
// (unless you cast away the const of course, don't do that).
// Critically here, everything happens at *runtime*.
const int MeaningOfLife = complex_initialization(1234, 5678, "hello");
// This guarantees that "MeaningOfLife" is fully evaluated and "initialized"
// *at compile time*.  If that is not possible due to complex_initialization()
// not being evaluatable at compile time, the compiler is required to abort
// compilation of the program.
// Critically here, to put a fine point on it, everything happens at
// *compile time*, guaranteed.  There won't be a runtime call to
// complex_initialization() at all in the final program.
constexpr int MeaningOfLife = complex_initialization(1234, 5678, "hello");

注意,是左边的常量使保证有存在的理由。当然,这取决于你是否能确保右边的值在编译时被求出来,重要的是,仅仅声明一个函数constexpr本身并不能做到这一点。

因此,您的问题的答案是,当您需要或希望它的初始化(右边发生的所有事情)完全在编译时发生或中断构建时,您应该声明一个变量constexpr。

你的基本例子和常数本身的例子是一样的。为什么要使用

static const int x = 5;
int arr[x];

over

int arr[5];

因为这样更容易维护。使用constexpr写和读要比现有的元编程技术快得多。

另一个用途(尚未提及)是constexpr构造函数。这允许创建编译时常量,这些常量不必在运行时进行初始化。

const std::complex<double> meaning_of_imagination(0, 42); 

将其与用户定义的字面量配对,就可以完全支持字面的用户定义类。

3.14D + 42_i;

它在某些方面很有用

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

int some_arr[MeaningOfLife()];

将它与特质类或类似的类联系起来,它会变得非常有用。