22

我说得对吗,那:

  • 用 定义的任何函数constexpr都是纯函数,并且
  • constexpr如果编译器的成本不是很高,则可以并且必须定义任何纯函数。

如果是这样,为什么 arent<cmath>的函数用 定义constexpr

4

4 回答 4

18

要补充其他人所说的内容,请考虑以下constexpr函数模板:

template <typename T>
constexpr T add(T x, T y) { return x + y; }

constexpr函数模板在某些情况下(例如 where Tis int)可用于常量表达式,但在其他情况下(例如 where is 具有未声明T的重载的类类型)。 operator+constexpr

constexpr并不意味着函数在常量表达式中总是可用的,它意味着函数可能在常量表达式中可用。

(有类似的例子涉及非模板函数。)

于 2011-03-28T17:09:22.140 回答
10

除了前面的答案:函数上的 constexpr 极大地限制了它的实现:它的主体必须对编译器可见(内联),并且必须只包含一个 return 语句。如果你能正确实现 sqrt() 或 sin() 并且仍然满足最后一个条件,我会感到惊讶。

于 2011-03-28T17:29:09.370 回答
8

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在编译时评估的......但是就运行时而言,它只是被一个常量替换。

于 2011-03-28T19:35:43.493 回答
-1

每个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函数的一个版本和一个在运行时使用的版本,我同意这样会很好,但标准说你不能重载constexprness。也许在 C++17 中......

于 2012-06-15T15:20:46.340 回答