这些可能应该在不同的问题中,但它们是相关的,所以......
-
为什么我们需要写constexpr
根本吗?给定一组限制,编译器无法评估代码以查看它是否满足constexpr
要求,并将其视为constexpr
如果有的话?作为一个纯粹的文档关键字,我不确定它是否成立,因为我无法想到我(其他人的用户)的情况constexpr
函数)应该真正关心它是否是运行时。
这是我的逻辑:如果它是一个昂贵的函数,我认为作为良好实践的问题,我应该这样对待它,无论我是否给它编译时常量输入。这可能意味着在加载时调用它并保存结果,而不是在执行的关键点调用它。原因是因为constexpr
实际上并不能向我保证它不会在运行时执行——所以也许一个新的/不同的机制应该做到这一点。
-
The constexpr限制 http://en.cppreference.com/w/cpp/language/constexpr似乎排除许多(如果不是大多数)函数在编译时被评估,这在逻辑上是可能的。我读过这至少部分(或可能全部?)是为了防止无限循环和挂起编译器。但是,如果这是the理由,合法吗?
对于任何给定的情况,编译器不应该能够计算 ifconstexpr
使用给定输入的函数会无限循环吗?这是not解决停止问题 https://en.wikipedia.org/wiki/Halting_problem for any输入。输入到一个constexpr
函数是编译时常数并且是有限的,因此编译器只需检查有限输入集的无限循环:实际使用的输入。如果您编写编译时无限循环,这应该是常规编译错误。
我问了一个非常相似的问题,为什么我们需要将函数标记为 constexpr? https://stackoverflow.com/questions/14472359/why-do-we-need-to-mark-functions-as-constexpr
When 我按了 https://groups.google.com/a/isocpp.org/d/msg/std-discussion/nrAu_YbCbYM/0eQsx6ip1DwJClang 作者 Richard Smith 解释道:
constexpr 关键字确实有用。
它会影响函数模板特化的实例化时间(如果在未计算的上下文中调用 constexpr 函数模板特化,则可能需要实例化它们;对于非 constexpr 函数则不然,因为对函数模板的调用永远不可能成为常量的一部分表达)。如果我们删除了关键字的含义,我们就必须尽早实例化更多的专业化,以防万一调用恰好是一个常量表达式。
它通过限制实现在翻译期间尝试评估的函数调用集来减少编译时间。 (这对于需要实现尝试常量表达式求值的上下文很重要,但如果此类求值失败,这不是错误 - 特别是静态存储持续时间的对象的初始值设定项。)
这一切一开始似乎并不令人信服,但如果你仔细研究细节,事情就会在不经意间就解开。constexpr
。函数在使用 ODR 之前不需要实例化,这本质上意味着在运行时使用。有什么特别之处constexpr
函数的缺点是它们可能违反此规则并且无论如何都需要实例化。
函数实例化是一个递归过程。实例化函数会导致其使用的函数和类的实例化,而不管任何特定调用的参数如何。
如果在实例化此依赖树时出现问题(可能会付出巨大的代价),则很难接受该错误。此外,类模板实例化可能会产生运行时副作用。
给定函数签名中依赖于参数的编译时函数调用,重载决策可能会导致函数定义的实例化,这些函数定义仅辅助重载集中的函数定义,包括甚至不被调用的函数。此类实例化可能会产生副作用,包括格式错误和运行时行为。
当然,这是一个极端的情况,但如果你不要求人们选择加入,那么糟糕的事情可能会发生constexpr
功能。
As for constexpr
对象,某些类型可以产生核心常量表达式无需声明即可在常量表达式上下文中使用constexpr
。但您并不真的希望编译器在编译时尝试评估每个表达式。这就是持续传播的目的。另一方面,记录某些事情似乎非常重要needs在编译时发生。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)