C++ 标准mandates编译器要检查未定义的行为 in C++ constexpr 计算.
In 这次演讲 https://www.youtube.com/watch?v=yG1OZ69H_-o,Chandler Carruth 指出,在检查 UB 时“你将耗尽检测错误的能力”,并且在一般情况下,检测 UB 与停止问题 https://en.wikipedia.org/wiki/Halting_problem,所以可以证明无法决定.
他不是在谈论 constexpr 中的 UB,而是constexpr 计算与 C++14 以来的常规程序一样通用,所以这仍然适用。
那么,当编译器无法确定程序是否是 UB 时,他们会做什么?他们是否仍然接受该程序并继续编译?或者他们是否更加保守并拒绝该计划,即使它可能是正确的? (我个人的感觉是他们这样做)
对我来说,这具有实际意义,因为我使用非平凡的指针算术进行了 constexpr 评估,用 Clang 编译得很好,但用 GCC 编译失败,而且我很确定这不是 UB。你可以说这是一个 GCC bug,但是如果 UB 是不可判定的,那么所有编译器在这方面都会存在 bug。
更根本的是,为什么要求不含 UB按标准?有技术原因吗?或者更多的是一种哲学(“如果编译器无法检查,程序员可以触发 UB,就会导致不好的结果”)?
我认为这与 C++ 的其余部分不一致,这永远不会阻止你搬起石头砸自己的脚。我希望 GCC 接受我的 constexpr 代码并崩溃,或者如果 UB 则发出垃圾;而不是在不知道是否是UB的情况下不编译。
======
EDIT ======
正如 M.M 和 Nicol Bolas 所指出的,该标准指定了限制(即使在 C++14 中也是如此),因此我们永远不会陷入 UB 的停止问题类型。然而,我仍然想知道检查 UB 是否可能太复杂,并且如果编译器启发式失败,那么它们会将其标记为非 constexpr(可能是错误的)。
但从评论中我感觉这更多是一个不成熟的实现问题。
您缺少的一点是常量表达式仅允许该语言的有限子集。
如果你超出了这个范围,你就不再有一个常量表达式,并且如果你处于需要一个常量表达式的上下文中,则标准要求诊断错误。
A constexpr
- 函数只需至少有一个输入,其中它是常量表达式,无需诊断。其余的可能都不是。
在一般情况下,编译器只是记录导致 UB 的路径,以修剪可能的死代码,并探索优化剩余代码的自由度。不过,他们并不需要找到所有、大部分甚至任何这些机会。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)