为什么我们需要将函数标记为constexpr? [英] Why do we need to mark functions as constexpr?

查看:366
本文介绍了为什么我们需要将函数标记为constexpr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 11允许使用 constexpr 说明符声明的函数在常量表达式(如模板参数)中使用。对于允许 constexpr 有严格的要求;基本上这样的函数只封装一个子表达式而不包含其他。 (编辑:这是放宽在C ++ 14,但问题是。)



为什么要求关键字? 获得的是什么?



它有助于揭示接口的意图,但它不会通过保证函数在常量表达式中可用来验证该意图。写入 constexpr 函数后,程序员必须仍然:


  1. 编写测试用例

  2. 记录在常量表达式上下文中有效的参数值。

与显示意图相反,使用 constexpr 装饰函数可能会增加一种错误的安全感,因为检查切向语法约束而忽略中心语义约束。 / p>




总之:如果 constexpr 在函数声明中只是可选的?

我按了理查德·史密斯,一个ang作者,他解释说:


constexpr关键字确实有效果。



它会影响当一个函数模板专门化实例化时(constexpr函数模板特化可能需要如果它们在未评估的上下文中被调用,则被实例化;对于非constexpr函数同样不是真的,因为对它的调用不能是常量表达式的一部分)。如果我们删除了关键字的含义,我们必须提前实例化更多的专业化,以防调用恰好是一个常量表达式。



编译时间,通过限制在翻译期间尝试评估所需实现的函数调用集合。 (这对于需要实现来尝试常量表达式求值的上下文是重要的,但是如果这样的求值失败,这不是一个错误 - 特别是静态存储持续时间的对象的初始化器。)




这一切似乎都不是令人信服的,但如果你仔细研究细节,事情就会解决,而不需要 constexpr 。函数不需要实例化,直到它是ODR使用,这本质上意味着在运行时使用。 constexpr 函数的特殊之处在于它们可以违反这个规则并需要实例化。



函数实例化是一个递归过程。



如果在实例化这个依赖关系树时出现错误(潜在地,显着的费用),这将是很难吞咽的错误。此外,类模板实例化可以具有运行时副作用。



给定在函数签名中的参数相关的编译时函数调用,重载解决可能导致函数定义的实例化只是辅助过载集中的那些,包括甚至不被调用的函数。这样的实例化可能会有副作用,包括形式不良和运行时行为。



这是一个确定的角落情况,但如果你不需要人选择加入 constexpr 函数。


C++11 allows functions declared with the constexpr specifier to be used in constant expressions such as template arguments. There are stringent requirements about what is allowed to be constexpr; essentially such a function encapsulates only one subexpression and nothing else. (Edit: this is relaxed in C++14 but the question stands.)

Why require the keyword at all? What is gained?

It does help in revealing the intent of an interface, but it doesn't validate that intent, by guaranteeing that a function is usable in constant expressions. After writing a constexpr function, a programmer must still:

  1. Write a test case or otherwise ensure it's actually used in a constant expression.
  2. Document what parameter values are valid in a constant expression context.

Contrary to revealing intent, decorating functions with constexpr may add a false sense of security since tangential syntactic constraints are checked while ignoring the central semantic constraint.


In short: Would there be any undesirable effect on the language if constexpr in function declarations were merely optional? Or would there be any effect at all on any valid program?

解决方案

When I pressed Richard Smith, a Clang author, he explained:

The constexpr keyword does have utility.

It affects when a function template specialization is instantiated (constexpr function template specializations may need to be instantiated if they're called in unevaluated contexts; the same is not true for non-constexpr functions since a call to one can never be part of a constant expression). If we removed the meaning of the keyword, we'd have to instantiate a bunch more specializations early, just in case the call happens to be a constant expression.

It reduces compilation time, by limiting the set of function calls that implementations are required to try evaluating during translation. (This matters for contexts where implementations are required to try constant expression evaluation, but it's not an error if such evaluation fails -- in particular, the initializers of objects of static storage duration.)

This all didn't seem convincing at first, but if you work through the details, things do unravel without constexpr. A function need not be instantiated until it is ODR-used, which essentially means used at runtime. What is special about constexpr functions is that they can violate this rule and require instantiation anyway.

Function instantiation is a recursive procedure. Instantiating a function results in instantiation of the functions and classes it uses, regardless of the arguments to any particular call.

If something went wrong while instantiating this dependency tree (potentially at significant expense), it would be difficult to swallow the error. Furthermore, class template instantiation can have runtime side-effects.

Given an argument-dependent compile-time function call in a function signature, overload resolution may incur instantiation of function definitions merely auxiliary to the ones in the overload set, including the functions that don't even get called. Such instantiations may have side effects including ill-formedness and runtime behavior.

It's a corner case to be sure, but bad things can happen if you don't require people to opt-in to constexpr functions.

这篇关于为什么我们需要将函数标记为constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆