如果一个函数只由return语句组成,那么它可以被声明为constexpr
,因此,如果所有参数都是constexpr
,并且其主体中仅调用constexpr
函数,则允许在编译时进行评估。 有什么理由不将任何这样的函数声明为constexpr
吗?
例如:
constexpr int sum(int x, int y) { return x + y; }
constexpr i = 10;
static_assert(sum(i, 13) == 23, "sum correct");
能否提供一个例子,说明声明一个函数为constexpr
会有什么坏处?
一些初始想法:
即使永远没有理由声明一个函数不是constexpr
,我可以想象constexpr
关键字具有过渡角色:在不需要编译时执行的代码中缺少它将允许不实现编译时执行的编译器仍然编译该代码(但在需要使用constexpr
显式指定的需要的代码上可靠地失败)。
但我不理解的是:如果永远没有理由去声明一个函数不是constexpr
,那么为什么标准库中不是每个函数都声明为constexpr
呢?(你不能认为还没有足够的时间来做到这一点,因为对于所有函数来说这是易如反掌的——与为每个单独的函数决定是否使其成为constexpr
相反。)
--- 我知道N2976故意不要求许多标准库类型(例如容器)具有cstrs,因为这对可能的实现来说太限制了。让我们将它们从参数中排除,只是想知道:一旦标准库中的类型实际上具有constexpr
的cstr,为什么不将作用于它的每个函数声明为constexpr
呢?
在大多数情况下,您也不能认为您可能不希望声明一个函数为constexpr
,只是因为您不预计任何编译时使用:因为如果其他人可能会使用您的代码,则他们可能会看到您没有看到的这样的用途。(但当然适用于类型特征类型和类似的东西。)
所以我想肯定有一个好的理由和一个好的例子来故意不声明一个函数为constexpr
吗?
(对于“每个函数”,我总是指:符合成为constexpr
的要求的每个函数,即定义为单个返回语句,仅使用具有constexpr cstrs类型的参数并调用仅使用constexpr
函数的函数。自C++14以来,在这样的函数体中允许更多内容:例如,C++14 constexpr函数可以使用本地变量和循环,因此可以声明一个更广泛的函数类为constexpr
。)
问题为什么std::forward
会丢弃constexpr
?是这个问题的一个特例。
constexpr
,则g++会忽略constexpr
,而不管输入是否为constexpr
。虽然我不确定这是否符合标准的意图,但对我来说这毫无意义。例如,将constexpr
函数的返回值分配给const int
将导致该函数出现在二进制文件中并被执行,而将其分配给一个枚举(具有相同的输入!)只是定义了一个枚举值,并且根本不生成代码。 - Damon