是否允许编译器在运行时调用立即(恒定)函数? [英] Is compiler allowed to call an immediate (consteval) function during runtime?

查看:102
本文介绍了是否允许编译器在运行时调用立即(恒定)函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是一个愚蠢的问题,但是我很困惑.我感觉在编译期间必须执行即时(consteval)函数 ,而我们根本无法在二进制文件中看到其主体.

This might be a stupid question, but I am confused. I had a feeling that an immediate (consteval) function has to be executed during compile time and we simply cannot see its body in the binary.

这篇文章明显支持我的感觉:

这意味着[immediate]函数仅在编译时可见.该函数不会发出符号,您不能使用该函数的地址,并且调试器之类的工具将无法显示它们.在这种情况下,立即函数类似于宏.

This has the implication that the [immediate] function is only seen at compile time. Symbols are not emitted for the function, you cannot take the address of such a function, and tools such as debuggers will not be able to show them. In this matter, immediate functions are similar to macros.

赫伯·萨特(Herb Sutter)的出版物:

请注意,C ++ 20草案已经包含了第一轮与反射相关的工作,并将其纳入该标准:约束函数保证在编译时运行,这些函数来自反射工作,并且专门用于处理反射信息.

Note that draft C++20 already contains part of the first round of reflection-related work to land in the standard: consteval functions that are guaranteed to run at compile time, which came from the reflection work and are designed specifically to be used to manipulate reflection information.

但是,有很多证据对此事实不太清楚.

However, there is a number of evidences that are not so clear about this fact.

来自 cppreference :

consteval-指定一个函数为立即函数,也就是说,每次对该函数的调用都必须产生一个编译时常量.

consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant.

这并不意味着它仅在编译时被调用.

It does not mean it has to be called during compile time only.

来自 P1073R3提案:

现在已经普遍同意,将来对反射的语言支持应该使用constexpr函数,但是由于通常在编译时对反射函数"进行评估,因此它们实际上很可能是立即函数.

There is now general agreement that future language support for reflection should use constexpr functions, but since "reflection functions" typically have to be evaluated at compile time, they will in fact likely be immediate functions.

看起来这就是我的想法,但是仍然不清楚.来自同一提议:

Seems like this means what I think, but still it is not clearly said. From the same proposal:

但是,有时我们想表达的是,函数在被调用时(直接或间接)应始终产生一个常数,而非常数结果应产生一个错误.

Sometimes, however, we want to express that a function should always produce a constant when called (directly or indirectly), and a non-constant result should produce an error.

同样,这并不意味着必须仅在编译时评估函数.

Again, this does not mean the function has to be evaluated during compile time only.

来自此答案:

您的代码必须产生一个编译时间常数表达式.但是,编译时常数表达式在您使用它的上下文中不是可观察的属性,并且在链接或甚至运行时时也没有副作用!而且在没有什么可以阻止的情况下

your code must produce a compile time constant expression. But a compile time constant expression is not an observable property in the context where you used it, and there are no side effects to doing it at link or even run time! And under as-if there is nothing preventing that

最后,有一个在线演示,其中在调用过程中明确调用了consteval函数运行.但是,我希望这是由于consteval在clang中尚未得到正确支持,并且该行为实际上是不正确的,就像在

Finally, there is a live demo, where consteval function is clearly called during runtime. However, I hope this is due to the fact consteval is not yet properly supported in clang and the behavior is actually incorrect, just like in Why does a consteval function allow undefined behavior?

更准确地说,我想听听被引用文章的以下哪些陈述是正确的:

To be more precise, I'd like to hear which of the following statements of the cited article are correct:

  1. 立即函数仅在编译时可见(并且无法在运行时评估)
  2. 不为立即函数发出符号
  3. 诸如调试器之类的工具将无法显示即时功能

推荐答案

更准确地说,我想听听被引用文章的以下哪些陈述是正确的:

To be more precise, I'd like to hear which of the following statements of the cited article are correct:

  1. 立即函数仅在编译时可见(并且无法在运行时评估)
  2. 不为立即函数发出符号
  3. 诸如调试器之类的工具将无法显示即时功能
  1. An immediate function is only seen at compile time (and cannot be evaluated at run time)
  2. Symbols are not emitted for an immediate function
  3. Tools such as debuggers will not be able to show an immediate function

这些几乎都不是C ++标准可以给出的答案.该标准没有定义符号"或工具可以显示的内容.就标准而言,几乎所有这些都是经销商的选择.

Almost none of these are answers which the C++ standard can give. The standard doesn't define "symbols" or what tools can show. Almost all of these are dealer's choice as far as the standard is concerned.

实际上,即使是编译时间"还是运行时间"的问题,该标准也没有解决.与标准有关的唯一问题是某物是否为常量表达式.调用constexpr函数 可能会产生一个常数表达式,具体取决于其参数.以不产生常量表达式的方式调用consteval函数的信息是不正确的.

Indeed, even the question of "compile time" vs. "run time" is something the standard doesn't deal with. The only question that concerns the standard is whether something is a constant expression. Invoking a constexpr function may produce a constant expression, depending on its parameters. Invoking a consteval function in a way which does not produce a constant expression is il-formed.

标准 定义的是可见"的内容.尽管它并不是真正意义上的编译时间".当前的C ++ 20草案中有许多语句禁止大多数函数处理指向立即函数的指针/引用.例如,N4835(C ++ 20的最新工作草案)在[expr.prim.id]/3中声明:

The one the standard does define is what gets "seen". Though it's not really about "compile time". There are a number of statements in the current C++20 draft that forbid most functions from dealing in pointers/references to immediate functions. For example, N4835 (the most current working draft of C++20) states in [expr.prim.id]/3:

表示立即函数的id表达式应仅出现

An id-expression that denotes an immediate function shall appear only

  • 作为立即调用的子表达式,或者

  • as a subexpression of an immediate invocation, or

在立即函数上下文中.

因此,如果您不在即时函数中,或者没有使用即时函数的名称来调用另一个即时函数(将指针/对该函数的引用传递),那么您将无法命名即时函数.而且,如果不命名该函数,就无法获得指向该函数的指针/引用.

So if you're not in an immediate function, or you're not using the name of an immediate function to call another immediate function (passing a pointer/reference to the function), then you cannot name an immediate function. And you can't get a pointer/reference to a function without naming it.

规范中的此声明和其他声明(例如指向立即函数的指针不存在常量表达式的有效结果)实质上使指向立即函数的指针/引用不可能泄漏到常量表达式之外.

This and other statements in the spec (like pointers to immediate function not being valid results of constant expressions) essentially make it impossible for a pointer/reference to an immediate function to leak outside of constant expressions.

因此,有关立即函数可见性的声明在某种程度上是正确的.可以为立即函数发出符号 ,但是不能以防止丢弃该符号的方式使用立即函数.

So statements about the visibility of immediate functions are correct, to some degree. Symbols can be emitted for immediate functions, but you cannot use immediate functions in a way that would prevent an implementation from discarding said symbols.

基本上,这就是consteval的问题.它不使用标准语言来强制执行必须发生的事情.它使用标准语言来使得不可能以防止发生的方式使用该功能.因此,更合理地说:

And that's basically the thing with consteval. It doesn't use standard language to enforce what must happen. It uses standard language to make it impossible to use the function in a way that will prevent these things from happening. So it's more reasonable to say:

  1. 您不能以阻止编译器在编译时执行它的方式使用立即函数.

  1. You cannot use an immediate function in a way that would prevent the compiler from executing it at compile time.

不能以阻止编译器为其丢弃符号的方式使用立即函数.

You cannot use an immediate function in a way that would prevent the compiler from discarding symbols for it.

您不能以强制调试器能够看到它们的方式使用立即函数.

You cannot use an immediate function in a way that would force debuggers to be able to see them.

实施质量有望从那里得到好处.

Quality of implementation is expected to take things from there.

还应注意,调试版本用于...调试.高级编译器工具能够调试生成常量表达式的代码是完全合理的.因此,可以看到立即执行功能的调试器是一项完全理想的技术.随着编译时代码变得越来越复杂,这一点变得越来越重要.

It should also be noted that debugging builds are for... debugging. It would be entirely reasonable for advanced compiler tools to be able to debug code that generates constant expressions. So a debugger which could see immediate functions execute is an entirely desirable technology. This becomes moreso as compile-time code grows more complex.

这篇关于是否允许编译器在运行时调用立即(恒定)函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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