我说得对吗,那:
- 用 定义的任何函数
constexpr
都是纯函数,并且 constexpr
如果编译器的成本不是很高,则可以并且必须定义任何纯函数。
如果是这样,为什么 arent<cmath>
的函数用 定义constexpr
?
要补充其他人所说的内容,请考虑以下constexpr
函数模板:
template <typename T>
constexpr T add(T x, T y) { return x + y; }
此constexpr
函数模板在某些情况下(例如 where T
is int
)可用于常量表达式,但在其他情况下(例如 where is 具有未声明T
的重载的类类型)。 operator+
constexpr
constexpr
并不意味着函数在常量表达式中总是可用的,它意味着函数可能在常量表达式中可用。
(有类似的例子涉及非模板函数。)
除了前面的答案:函数上的 constexpr 极大地限制了它的实现:它的主体必须对编译器可见(内联),并且必须只包含一个 return 语句。如果你能正确实现 sqrt() 或 sin() 并且仍然满足最后一个条件,我会感到惊讶。
constexpr
函数不是pure
因为它是对编译器的提示,即如果函数的参数是常量并且函数体中提到的操作(对于这些参数)本身就是函数,constexpr
则该函数可以在编译期间计算。constexpr
后者,使用模板代码,允许我们演示一个不纯的constexpr
函数:
template <typename T>
constexpr T add(T lhs, T rhs) { return lhs + rhs; }
用这种类型实例化
DebugInteger operator+(DebugInteger lhs, DebugInteger rhs) {
printf("operator+ %i %i", lhs._value, rhs._value);
return DebugInteger(lhs._value + rhs._value);
}
这里,operator+
不是 constexpr,因此可以读/写全局状态。
我们可以说一个constexpr
函数是pure
在编译时评估的......但是就运行时而言,它只是被一个常量替换。
每个constexpr
函数都是纯函数,但不是每个纯函数都可以或应该是constexpr
.
[Examples involving constexpr
function templates are misleading, since function templates are not functions, they're patterns by which the compiler can generate functions. The outcome of function templates, their specialisations, are functions and they will be constexpr
iff possible.]
A pure function is one that only depends on its arguments, or other constant state. That's pretty much what a constexpr
function is. In addition, constexpr
functions must be defined (not only declared) prior to their first use (recursion seems to be allowed, though), and must consist of only the return statement. That's enough to make the allowed subset Turing-complete, but the result is not necessarily the most efficient form at runtime.
这将我们带到了数学函数。您可能可以实现constexpr
sqrt()
or sin()
,但他们必须使用编译器可以在编译时评估的递归实现,而在运行时,这些最好在一个汇编程序操作中实现。由于and的constexpr
使用很少而且相距甚远,因此最好最大化运行时性能,这需要一种无法实现的形式。sqrt()
sin()
constexpr
你可能想知道为什么你不能编写一个constexpr
函数的一个版本和一个在运行时使用的版本,我同意这样会很好,但标准说你不能重载constexpr
ness。也许在 C++17 中......