为什么**不**要声明一个函数`constexpr`?
任何由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
显示需要的代码时可靠地失败)。
但是我不明白:如果没有充分的理由宣布一个function不够完善的话,为什么标准库中的每一个function都没有被宣告为constexpr
? (你不能争辩说还没有完成,因为还没有足够的时间去做,因为这样做是毫不费力的 – 与决定每一个单一function是否相反)。 – – 我知道, N2976故意不要求许多标准库types(如容器)的cstrs,因为这对于可能的实现来说太过于限制。 让我们把它们排除在参数之外,只是想知道:一旦标准库中的types实际上有一个constexpr
cstr,为什么不是每个函数都声明为constexpr
呢?
在大多数情况下,你也不能争辩说,你可能宁愿不去声明一个函数constexpr
只是因为你没有设想任何编译时间的用法:因为如果其他人evtl. 将使用你的代码,他们可能会看到你不这样使用。 (但是,当然,types特征types和东西都是可以的。)
所以我想有一个很好的理由和一个很好的例子,故意不宣布函数constexpr
?
(“每一个function”,我的意思是:每一个符合被constexpr
要求的函数,也就是被定义为一个单一的return语句,只带有constexprcrstypes的参数,只调用constexpr
函数。
问题为什么std::forward
放弃了constexpr
-ness? 这是一个特例。
函数只有遵循constexpr
的规则才能声明为constexpr
—没有dynamic转换,没有内存分配,没有对非constexpr
函数的调用等
在标准库中声明一个函数为constexpr
要求所有的实现都遵守这些规则。
首先,这需要检查每个函数,它可以作为constexpr
来实现,这是一个长期的工作。
其次,这是对实现的一个很大的限制,并且将许多debugging实现排除在外。 因此,如果收益大于成本,或者要求足够严格,那么实施必须遵守constexpr
规则。 对每个function进行评估再次是一个长期的工作。
我认为你所指的是部分评估 。 你所触及的是一些程序可以分为两部分 – 一部分需要运行时信息,一部分可以在没有任何运行时信息的情况下完成 – 理论上你可以完全评估程序部分在开始运行程序之前,不需要任何运行时信息。 有一些编程语言可以做到这一点。 例如,D编程语言在编译器中内置了一个解释器,它允许您在编译时执行代码,前提是符合某些限制。
获得部分评估工作有几个主要挑战。 首先,它使编译器的逻辑显着复杂化,因为编译器需要能够模拟编译时可以放入可执行程序的所有操作。 在最坏的情况下,这要求你在编译器内部有一个完整的解释器,这是一个很难的问题(编写一个好的C ++编译器),并且难以做到这一点。
我认为目前关于constexpr
规范的原因是简单地限制了编译器的复杂性。 这种情况是有限的,检查相当简单。 不需要在编译器中实现循环(这可能会导致其他一系列问题,比如在编译器中出现无限循环时会发生什么情况)。 它还避免了编译器潜在地必须评估在运行时可能导致段错误的语句,例如跟随错误的指针。
另外需要注意的是,一些function有副作用,如从cin
读取或打开networking连接。 像这样的function从根本上说不能在编译时进行优化,因为这样做只需要在运行时可用的知识。
总而言之,没有理论上的原因,你不能在编译时部分评估C ++程序。 事实上,人们总是这样做。 例如,优化编译器本质上就是试图尽可能地做到这一点的程序。 模板元编程是C ++程序员试图在编译器内部执行代码的一个例子,部分模板可以做一些很棒的事情,因为模板规则形成了一种function语言,编译器可以更容易地实现。 此外,如果您想到编译器作者的小时数和编程时间之间的权衡,模板元编程表明,如果您可以让程序员向后弯曲以获得他们想要的,可以构build一个相当弱的语言(模板系统)并保持语言复杂度很简单。 (在可计算性理论意义上,我认为是“弱”,如“不是特别performance力”,而不是“弱”)。
希望这可以帮助!
如果这个函数有副作用,你不想标记为constexpr
。 例
我无法得到任何意想不到的结果,实际上它看起来像海湾合作委员会4.5.1只是忽略了constexpr