“constexpr”函数的“noexcept”行为

2024-04-19

的措辞[expr.unary.noexcept]改变于C++17.


之前 (n4140, 5.3.7 noexcept 运算符 [expr.unary.noexcept] https://timsong-cpp.github.io/cppwp/n4140/expr.unary.noexcept), 我的重点:

  1. The result of the noexcept operator is false if in a potentially-evaluated context the expression would contain

    (3.1) 对函数、成员函数的潜在评估调用, 函数指针,或没有成员函数指针 非抛出异常规范([except.spec]),除非打电话 是一个常量表达式 ([expr.const]) ...


Now1 (7.6.2.6 noexcept operator [expr.unary.noexcept] https://eel.is/c++draft/expr.unary.noexcept):

  1. noexcept 运算符的结果是true除非表达式可能抛出异常([ except.spec] )。

然后在14.5 异常规范[ except.spec ] https://eel.is/c++draft/except.spec:

  1. 如果函数的声明没有 noexcept 说明符,则该声明具有可能引发异常的说明,除非...

but the 除非列出14.5(3) 未列出constexpr,将其保留为可能抛出...

1 a link to C++17 n4659 https://timsong-cpp.github.io/cppwp/n4659/except.spec#6 added by L.F. in a comment.


测试代码

constexpr int f(int i) { return i; }

std::cout << boolalpha << noexcept(f(7)) << std::endl;
int a = 7;
std::cout << boolalpha << noexcept(f(a)) << std::endl;

用于打印(与海湾合作委员会8.3 https://godbolt.org/z/ivAnRa):

true
false

两者都在编译时使用-std=c++11 and -std=c++2a


However现在打印相同的代码(与海湾合作委员会9.2 https://godbolt.org/z/GWUEdg):

false
false

两者都在编译时使用-std=c++11 and -std=c++2a


顺便说一句,Clang 非常一致,从3.4.1开始 https://godbolt.org/z/UsBDok并与:

false
false

  • 每个规范的正确行为是什么?
  • 规格有真正的变化吗?如果是这样,这种变化的原因是什么?
  • 如果规范中的更改影响或与过去的行为相矛盾,那么常见的做法是强调这种变化及其影响?如果改变是没有强调这是否意味着它可能是监督?
  • 如果这是真正有意的更改,是否认为它是一个错误修复,应该追溯到规范的先前版本,编译器是否正确地将新行为追溯至 C++11?

Side Note: the noexcept deduction on a constexpr function affects this trick https://stackoverflow.com/a/35110453/2085626.


Summary

每个规范的正确行为是什么?

true false在 C++17 之前,false false从 C++17 开始。

规格有真正的变化吗?如果是这样,这种变化的原因是什么?

是的。请参阅下面 Clang 错误报告中的引用。

如果规范发生影响或与过去相矛盾的变化 行为,强调改变和 它的影响是什么?如果不强调这一变化是否意味着它 可能是一个疏忽?

是的;是的(但 CWG 后来找到了一个理由来证明这一监督是合理的,因此保持原样)。

如果这是真正有意的更改,是否被视为错误修复 应该回到规范的早期版本,编译器是否正确 将新行为追溯至 C++11?

我不知道。请参阅下面 Clang 错误报告中的引用。

Detail

我找了很多地方,目前能找到的最接近的就是相关bug报告的评论:

  • GCC Bug 87603 - [C++17] noexcept 不再是常量表达式的特殊情况 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87603

    CWG 1129(最终以 C++11 形式出现)添加了一个特殊情况noexcept对于常量表达式,因此:

    constexpr void f() {} static_assert(noexcept(f()));
    

    CWG 1351(最终采用 C++14)显着改变了措辞, 但特殊情况仍然存在,只是形式不同。

    P0003R5(最终出现在 C++17 中)再次更改了措辞,但是 特殊情况被删除(意外),所以现在:

    constexpr void f() {} static_assert(!noexcept(f()));
    

    根据 LLVM 15481 中的 Richard Smith 的说法,CWG 对此进行了讨论,但决定保持该行为不变。目前,clang 做得对 对于 C++17 来说是这样的(对于 C++14 和 C++11 来说是故意失败的)。克++, 然而,已经实现了 C++11 的特殊情况,但还没有实现 C++17 的更改。目前,icc 和 msvc 的行为似乎与 g++ 类似。

  • Clang Bug 15481 - noexcept 应该检查表达式是否是常量表达式 https://bugs.llvm.org/show_bug.cgi?id=15481

    常量表达式特殊情况被 wg21.link/p0003 删除了——显然是偶然的。我正在调查是否会进行 是否离开。

    您是否采取了任何措施来避免深度嵌套的二次运行时 表达式?

    [...]

    CWG 讨论的结论:我们将保持原样。noexcept对于常量表达式没有特殊的规则。

    事实证明这对于正确的图书馆来说实际上是必不可少的 功能:例如,如果noexcept尝试评估其操作数,然后 (例如)is_nothrow_swappable因制造而被打破std::swap constexpr, 因为std::swap<T>然后经常会得到 之前实例化过T做完了。

    因此,我还将将此更改视为 针对 C++11 和 C++14 的有效 DR...但我愿意重新考虑 如果我们看到很多用户投诉。

换句话说,特殊规则被意外地删除了P0003 https://wg21.link/p0003,但 CWG 决定保留删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“constexpr”函数的“noexcept”行为 的相关文章

  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • 无法使用已与其底层 RCW 分离的 COM 对象。在 oledb 中

    我收到此错误 但我不知道我做错了什么 下面的代码在backrgroundworker中 将异常详细信息复制到剪贴板 System Runtime InteropServices InvalidComObjectException 未处理 通
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的
  • WCF:将随机数添加到 UsernameToken

    我正在尝试连接到用 Java 编写的 Web 服务 但有些东西我无法弄清楚 使用 WCF 和 customBinding 几乎一切似乎都很好 除了 SOAP 消息的一部分 因为它缺少 Nonce 和 Created 部分节点 显然我错过了一
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐