为什么**不**声明一个函数是`constexpr`?

时间:2011-02-25 00:34:31

标签: c++ c++11 const constexpr function-declaration

只能声明由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的要求,即被定义为单一 return语句,只接受带有constexpr的类型的参数 cstrs和仅调用constexpr个函数。)

问题Why does std::forward discard constexpr-ness? 这是一个特例。

3 个答案:

答案 0 :(得分:33)

如果函数遵守constexpr的规则---没有动态强制转换,没有内存分配,没有调用非constexpr函数等,则只能声明函数constexpr。 / p>

将标准库中的函数声明为constexpr要求所有实现都遵循这些规则。

首先,这需要检查可以实现为constexpr的每个功能,这是一项很长的工作。

其次,这是对实现的一个很大的限制,并且将禁止许多调试实现。因此,如果收益大于成本,或者要求足够严格以至于实施几乎必须遵守constexpr规则,那么这是值得的。对每个功能进行评估也是一项很长的工作。

答案 1 :(得分:14)

我认为你所指的是partial evaluation。您所接触的是,某些程序可以分为两部分 - 一部分需要运行时信息,一部分可以在没有任何运行时信息的情况下完成 - 理论上您可以完全评估程序的一部分在开始运行程序之前不需要任何运行时信息。有一些编程语言可以做到这一点。例如,D编程语言在编译器中内置了一个解释器,允许您在编译时执行代码,前提是它满足某些限制。

部分评估工作存在一些主要挑战。首先,它使编译器的逻辑变得非常复杂,因为编译器需要能够模拟在编译时可以放入可执行程序的所有操作。在最糟糕的情况下,这需要你在编译器内部有一个完整的解释器,这就产生了一个难题(编写一个好的C ++编译器)并使其难以达到数量级。

我认为当前关于constexpr的规范的原因仅仅是限制编译器的复杂性。它受限的情况很容易检查。没有必要在编译器中实现循环(这可能会导致另外一大堆问题,例如,如果在编译器中获得无限循环会发生什么)。它还避免了编译器可能必须评估可能在运行时导致段错误的语句,例如跟踪错误的指针。

要记住的另一个考虑因素是某些功能会产生副作用,例如从cin读取或打开网络连接。这些函数从根本上无法在编译时进行优化,因为这样做只需要在运行时才能获得的知识。

总而言之,理论上没有理由说你无法在编译时部分评估C ++程序。事实上,人们总是这样做。例如,优化编译器本质上是试图尽可能地执行此操作的程序。模板元编程是C ++程序员尝试在编译器中执行代码的一个实例,并且可以使用模板做一些很好的事情,因为模板规则构成了一种函数式语言,编译器可以更容易地实现。此外,如果您考虑编译器作者小时和编程时间之间的权衡,模板元编程表明,如果您可以让程序员向后弯腰以获得他们想要的东西,您可以构建一个非常弱的语言(模板系统)并保持语言复杂性简单。 (我说“弱”,如“不特别表达”,而不是“可计算性理论意义上的”弱“)。

希望这有帮助!

答案 2 :(得分:3)

如果该功能有副作用,您不希望将其标记为constexprExample

我无法从中获得任何意外结果,实际上它看起来像gcc 4.5.1 just ignores constexpr