我是对的,那个:
constexpr
定义的任何功能都是pure function和constexpr
定义,如果它对编译器来说不是很昂贵。如果是这样,为什么<cmath>
的函数不是用constexpr
定义的?
答案 0 :(得分:17)
要添加其他人所说的内容,请考虑以下constexpr
函数模板:
template <typename T>
constexpr T add(T x, T y) { return x + y; }
此constexpr
函数模板在某些情况下可用于常量表达式(例如,T
为int
)但在其他情况下不可用(例如,T
为operator+
具有constexpr
重载但未声明为constexpr
的类类型。
{{1}}并不意味着函数始终可用于常量表达式,这意味着函数可能可用于常量表达式。< / p>
(有类似的例子涉及非模板函数。)
答案 1 :(得分:9)
除了以前的答案:constexpr对函数的限制 它的实现很大:它的主体必须对编译器可见 (内联),并且必须仅包含一个return语句。我会 如果你能正确地实现sqrt()或sin(),那就很惊讶了 满足最后的条件。
答案 2 :(得分:7)
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
...但就运行时而言,它只是被一个常量替换。
答案 3 :(得分:-1)
每个constexpr
函数都是纯函数,但不是每个纯函数都可以或应该是constexpr
。
[涉及constexpr
函数模板的示例具有误导性,因为函数模板不是函数,它们是编译器可以生成函数的模式。函数模板的结果,它们的特化,是函数,如果可能,它们 将constexpr
。]
纯函数是仅依赖于其参数或其他常量状态的函数。这几乎就是constexpr
函数。此外,constexpr
函数必须在第一次使用之前定义(不仅声明)(但似乎允许递归),并且必须仅包含return语句。这足以使得允许的子集Turing-complete,但结果不一定是运行时最有效的形式。
这将我们带到了数学函数。您可以实现constexpr
sqrt()
或sin()
,但是他们必须使用编译器可以在编译时评估的递归实现,而在运行时,这些实现更好一个汇编操作。由于constexpr
和sqrt()
的{{1}}使用很少且距离较远,因此最好最大限度地提高运行时性能,这需要一个不具有sin()
能力的表单。
你可能想知道为什么你不能写一个constexpr
版本的函数和一个在运行时使用的版本,我同意这样做很好,但标准说你不能超载在constexpr
上。也许在C ++ 17 ...