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

// preprocessor.
#define MEANING_OF_LIFE 42

// constants:
const int MeaningOfLife = 42;

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

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


当前回答

它在某些方面很有用

// constants:
const int MeaningOfLife = 42;

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

int some_arr[MeaningOfLife()];

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

其他回答

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

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

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

3.14D + 42_i;

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做一件很棒的事情。See-Phit (https://github.com/rep-movsd/see-phit/blob/master/seephit.h)是一个编译时HTML解析器和模板引擎。这意味着您可以放入HTML,然后取出能够操作的树。在编译时进行解析可以提供一些额外的性能。

从github页面的例子:

#include <iostream>
#include "seephit.h"
using namespace std;



int main()
{
  constexpr auto parser =
    R"*(
    <span >
    <p  color="red" height='10' >{{name}} is a {{profession}} in {{city}}</p  >
    </span>
    )*"_html;

  spt::tree spt_tree(parser);

  spt::template_dict dct;
  dct["name"] = "Mary";
  dct["profession"] = "doctor";
  dct["city"] = "London";

  spt_tree.root.render(cerr, dct);
  cerr << endl;

  dct["city"] = "New York";
  dct["name"] = "John";
  dct["profession"] = "janitor";

  spt_tree.root.render(cerr, dct);
  cerr << endl;
}

曾经有一种元编程模式:

template<unsigned T>
struct Fact {
    enum Enum {
        VALUE = Fact<T-1>*T;
    };
};

template<>
struct Fact<1u> {
    enum Enum {
        VALUE = 1;
    };
};

// Fact<10>::VALUE is known be a compile-time constant

我相信引入constexpr是为了让你编写这样的构造,而不需要模板和带有特化的奇怪构造,SFINAE之类的东西——但就像你编写一个运行时函数一样,但保证结果将在编译时确定。

但是,请注意:

int fact(unsigned n) {
    if (n==1) return 1;
    return fact(n-1)*n;
}

int main() {
    return fact(10);
}

用g++ -O3编译它,你会看到事实(10)确实在编译时被求值了!

一个VLA-aware编译器(C99模式下的C编译器或带有C99扩展的c++编译器)甚至可以允许你做:

int main() {
    int tab[fact(10)];
    int tab2[std::max(20,30)];
}

但目前它是非标准的c++ - constexpr看起来是一种解决这个问题的方法(即使没有VLA,在上面的例子中)。还有一个问题,就是需要有“正式的”常量表达式作为模板参数。

刚刚开始将一个项目切换到c++11,遇到了一个非常好的constexpr情况,它清理了执行相同操作的替代方法。这里的关键点是,只有当函数声明为constexpr时,才能将其放入数组大小声明中。在许多情况下,我可以看到这在我所从事的代码领域非常有用。

constexpr size_t GetMaxIPV4StringLength()
{
    return ( sizeof( "255.255.255.255" ) );
}

void SomeIPFunction()
{
    char szIPAddress[ GetMaxIPV4StringLength() ];
    SomeIPGetFunction( szIPAddress );
}