constexpr 函数中的 Consteval 构造函数和成员函数调用

2024-01-08

struct A {       
    int i;
    consteval A() { i = 2; };
    consteval void f() { i = 3; }
};

constexpr bool g() {
    A a;
    a.f();
    return true;
}

int main() {
    static_assert(g());
}

https://godbolt.org/z/hafcab7Ga https://godbolt.org/z/hafcab7Ga

该计划被 GCC、Clang、MSVC 和 ICC 全部拒绝,并替换constexpr on g by consteval结果四个人都接受了。

但是,当删除呼叫时a.f();,仍然与constexpr on g,只有 ICC 仍然拒绝该代码。其他三人现在也都接受了。

我不明白为什么会这样。我的理解是如果没有consteval on g, 表达方式a.f()不在立即函数上下文,这将导致成员函数调用本身被计算为单独的常量表达式,从而无法修改i成员,因为该成员的生命周期不是在该常量表达式求值期间开始的。

但为什么构造函数可以在相同的上下文中对同一个对象执行相同的操作呢?是a的生命周期被认为是在 consteval 构造函数求值期间开始的吗?


另请注意,static_assert不影响这些结果。另外删除constexpr完全来自gthen 也不会改变编译器行为的任何内容。


正如@Enlico 所指出的,甚至替换两者A a; and a.f(); by A{}.f(); with constexpr on g结果是除了 ICC 之外的所有编译器都接受代码,尽管根据我的理解,这个表达式应该导致对立即构造函数调用和立即成员函数调用的两个单独的常量表达式进行求值。我认为后一个调用的行为应该与a.f();,使这变得更加混乱。

(读完@Barry的回答后,我现在意识到最后一句话没有任何意义。更正:A{}将是构造函数立即调用的一个常量表达式,A{}.f()作为一个整体,将是成员函数立即调用的第二个常量表达式。这与表达方式明显不同a.f().)


规则是,从[表达式常量]/13 https://timsong-cpp.github.io/cppwp/n4861/expr.const#13:

表达式或转换位于立即函数上下文如果它可能被评估并且其最内部的非块作用域是立即函数的函数参数作用域。表达式或转换是立即调用如果它是立即函数的潜在评估显式或隐式调用并且不在立即函数上下文中。立即调用应是常量表达式。

其中,立即函数只是术语(来自[dcl.constexpr]/2 https://timsong-cpp.github.io/cppwp/n4861/dcl.constexpr#2):

使用以下声明的函数或构造函数consteval说明符被称为立即函数.

从例子来看:

struct A {       
    int i;
    consteval A() { i = 2; };
    consteval void f() { i = 3; }
};

constexpr bool g() {
    A a;
    a.f();
    return true;
}

电话a.f()是立即调用(我们正在调用立即函数,但我们不在立即函数上下文中,g is constexpr not consteval),所以它一定是一个常量表达式。

它本身必须是一个常量表达式。不是整个调用g(), just a.f().

是吗?不。a.f()变异a通过写入a.i,这违反了[表达式常量]/5.16 https://timsong-cpp.github.io/cppwp/n4861/expr.const#5.16。作为常量表达式的限制之一是不能:

对象的修改([expr.ass]、[expr.post.incr]、[expr.pre.incr]),除非它应用于引用其非易失性对象的文字类型的非易失性左值生命周期开始于评估E;

我们的对象,a.i,并没有在该表达式的求值过程中开始其生命周期。因此,a.f()不是常量表达式,因此所有编译器都可以正确拒绝。

值得注意的是A().f();会很好,因为现在我们遇到了异常 -A()在评估该表达式期间开始其生命周期,因此A().i也做了,因此分配给它就可以了。

你可以认为这意味着A()对于常量求值器来说是“已知”的,这意味着做A().i = 3;完全没问题。同时,a未知 - 所以我们不能做a.i = 3;因为我们不知道什么a is.


If g() were a consteval函数,则a.f()将不再是立即调用,因此我们不再要求它本身是一个常量表达式。现在唯一的要求就是g()是一个常量表达式。

并且,在评估时g()作为常量表达式,声明A a;现在在表达式的求值范围内,所以a.f()并不能阻止g()从一个常数表达式。


规则差异的产生是因为consteval函数需要是only在编译时调用,以及constexpr函数仍然可以在运行时调用。

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

constexpr 函数中的 Consteval 构造函数和成员函数调用 的相关文章

  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 我如何理解这个 C 类型声明?

    double bar int double double double double 在查看讲座幻灯片时 我发现了留给学生的练习 用简单的英语来说 什么是类型bar在这个 C 声明中 Please帮助我解决这个问题 我什至不知道从哪里开始
  • 使用 Enumerable.OfType() 或 LINQ 查找特定类型的所有子控件

    Existed MyControl1 Controls OfType
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 根据 N 个值中最小的一个返回不同的结果

    不确定如何使标题更具描述性 所以我只是从一个例子开始 我使用下面的代码位 它从枚举中选择一个方向 具体取决于四个轴中哪一个与给定方向相比形成最小角度 static Direction VectorToDirection Vector2 di
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 在 JSQMessagesViewController 中显示 LocationMediaItem

    我刚刚尝试实施LocationMediaItem in my Xamarin iOS应用程序使用JSQMessagesViewController 一切都很顺利 唯一的问题是UICollectionView应该显示位置的单元格永远停留在加载
  • 从 WebBrowser 控件 C# 获取滚动值

    我试图在 WebBrowser 控件中获取网页的 Y 滚动索引 但无法访问内置滚动条的值 有任何想法吗 对于标准模式下的 IE 使用文档类型 正如你所说 scrollTop是的财产元素 而不是 HtmlDocument htmlDoc th
  • AES 输出是否小于输入?

    我想加密一个字符串并将其嵌入到 URL 中 因此我想确保加密的输出不大于输入 AES 是可行的方法吗 不可能创建任何始终会创建比输入更小的输出的算法 但可以将任何输出反转回输入 如果您允许 不大于输入 那么基本上您只是在谈论同构算法alwa
  • 如何分析组合的 python 和 c 代码

    我有一个由多个 python 脚本组成的应用程序 其中一些脚本正在调用 C 代码 该应用程序现在的运行速度比以前慢得多 因此我想对其进行分析以查看问题所在 是否有工具 软件包或只是一种分析此类应用程序的方法 有一个工具可以将 python
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • 更改 Windows Phone 系统托盘颜色

    有没有办法将 Windows Phone 上的系统托盘颜色从黑色更改为白色 我的应用程序有白色背景 所以我希望系统托盘也是白色的 您可以在页面 XAML 中执行此操作
  • 矩阵到数组 C#

    这将是转换方阵的最有效方法 例如 1 2 3 4 5 6 7 8 9 into 1 2 3 4 5 6 7 8 9 in c 我在做 int array2D new int 1 2 3 4 5 6 7 8 9 int array1D new
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959

随机推荐

  • 将两个 ArrayList 添加到一个哈希图 ArrayList

    我有两个ArrayList我想做一个ArrayList通过添加它们 两个列表具有相同的大小 我打算这样做 这是优化的还是当列表变大时我可以让它变得更好 更高效 i e private ArrayList
  • Material UI:样式闪烁然后消失

    在此 SSR 应用程序的以下代码中 样式可能会出现 50 毫秒并消失 我很好奇是什么原因造成的 This component is a child of index tsx in the pages folder
  • GitHub - 如何从一个分支创建两个拉取请求

    我已经分叉了一个开源存储库 在我的分叉上编写了数千行代码 并在原始项目上创建了拉取请求 与此同时 我修复了另一个与我的第一个拉取请求完全无关的错误 我想专门针对此错误创建第二个拉取请求 它不包含第一个拉取请求中的任何工作 不需要我再次分叉存
  • 在Java中模拟鼠标在非活动窗口的某个位置单击?

    不管怎样 我正在构建一个在后台运行的机器人 这个机器人需要我点击 当然 我希望能够在机器人运行时做其他事情 所以我想知道是否可以在非活动窗口的某个位置模拟鼠标单击 如果可能的话 如果你们中有人能帮助我 我将不胜感激 java awt Rob
  • 在 Xamarin 中创建自定义控件

    我正在将我的应用程序从 Windows Phone 8 移植到 Android 并且我需要创建一些自定义 UI 控件 我尝试创建一个 XML 布局 在其中创建一个 LinearLayout 作为控件 然后动态添加它 根据用户的意愿 但这不起
  • 如何使用 PHP 实现工厂类 - 依赖注入

    以下面的代码作为我想要的示例 class SomethingController extends Factory private somethingRepository public function Construct ISomethin
  • 如何使用现有的 pom.xml 将 3rd 方文件发布到远程 Maven 存储库?

    我有一些第三方 jar 想要上传到我的 Nexus maven 存储库 到目前为止我已经找到了两种方法来做到这一点 使用 Nexus GUI 使用以下说明 http maven apache org guides mini guide 3r
  • 这是什么时间格式?如何将其转换为标准化的 dd/mm/yyyy 日期?

    我正在使用 YouTube Google API 对于特定视频的上传日期 将返回以下格式的时间 日期 2012 05 16T17 15 29 000Z 我不确定这是什么格式 但我想知道是否有一种简单的方法 例如使用DateTime 将其转换
  • 使用 folium 中的地理数据框绘制彩色多边形

    我正在尝试在 folium 中绘制雷达数据 而且我已经快完成了 我按照这个例子 在边界内绘制等高线图数据 纬度 经度 值 并导出 GeoJSON https stackoverflow com questions 34886899 cont
  • 在 Android 上解析 ~1 MB JSON 非常慢

    我的资产文件夹中存储了一个大约 1MB 的 JSON 文件 每次运行时我都需要在应用程序中加载该文件 我发现内置的 JSON 解析器 org json 解析文件的速度非常慢 但是一旦解析完成 我就可以非常快速地访问和操作数据 我计算出从我点
  • glib2 是否真的会使用 ALWAYS-MALLOC 泄漏内存?

    这个问题是not许多其他人的重复 因为我do use G DEBUG gc friendly and G SLICE always malloc这是源代码 include
  • 在 Laravel 中全局缓存表值

    我有一张表 模型的设置Setting class Setting extends Model protected fillable name value 我创建了一个服务提供SettingsServiceProvider并注册于app ph
  • “docker 容器运行”需要至少 1 个参数

    我正在尝试使用已创建的卷创建容器 但我的控制台显示错误 docker container run requires at least 1 argument 这是我试图运行的命令 docker container run name db v
  • 如何按指定顺序连接字符串

    尝试从这篇文章中对角连接字符串如何交替连接 3 个字符串 https stackoverflow com questions 24346355 how to alternatively concatenate 3 strings 但没有成功
  • 仅在模态窗格内保持 Tab 键切换

    在我当前的项目中 我们有一些在某些操作上打开的模式窗格 我试图获取它 以便当该模式窗格打开时 您无法使用 Tab 键切换到它之外的元素 jQuery UI 对话框和 Malsup jQuery 块插件似乎可以做到这一点 但我试图获得这一功能
  • 安装超集:错误:命令“gcc”失败,退出状态为 1

    我正在尝试在 CentOS 7 上安装 Superset 我已按照官方网站进行操作阿帕奇超级集 https superset incubator apache org installation html 我已经安装了所有必需的依赖项 sud
  • 将 MS Access 表拆分为多个部分并使用 VBA 导出到 Excel

    我有一个包含大约 50000 条记录的 Access 表 我需要将其最好分成 3 个部分 并使用 VBA 将这些部分导出到单独的 Excel 文件或工作表中 我需要这个 因为这些 Excel 文件在其他地方使用 文件中的最大记录数只能约为
  • 如何检测 DOMContentLoaded 是否被触发

    我正在尝试帮助开发一个库 并为此尝试处理页面加载 在这个过程中我想让库完全兼容 defer 和 async 的使用 我想要的很简单 我如何知道 DOMContentLoaded 在文件执行时被触发 为什么这么难 在 IE 中 documen
  • 关闭 Typeahead.js 的选项卡

    我正在我的一个文本框上使用预输入 typeahead js https github com twitter typeahead js blob master README md 我正在尝试关闭选项卡自动完成 我在文档中找不到这个 但也许有
  • constexpr 函数中的 Consteval 构造函数和成员函数调用

    struct A int i consteval A i 2 consteval void f i 3 constexpr bool g A a a f return true int main static assert g https