std::chrono::duration::duration() 如何成为 constexpr?

2024-02-23

默认构造函数std::chrono::duration定义如下:

constexpr duration() = default;

(例如,参见cppreference.com http://en.cppreference.com/w/cpp/chrono/duration/duration或 libstdc++ 源。)

然而,cppreference.com 也这么说 http://en.cppreference.com/w/cpp/language/constexpr about constexpr构造函数:

constexpr 构造函数必须满足以下要求:

...

每个基类和每个非静态成员都必须初始化,可以在构造函数初始化列表中,也可以通过成员大括号或等号初始化程序。此外,涉及的每个构造函数都必须是 constexpr 构造函数,并且每个大括号或等于初始值设定项的每个子句都必须是常量表达式

如果我对默认构造函数感到困惑,cppreference.com 似乎说 http://en.cppreference.com/w/cpp/language/default_constructor默认构造函数是与= default与隐式默认构造函数的定义没有不同。

然而,rep(大多数)持续时间的类型是裸整数类型。所以,不应该明确= default默认构造函数duration相当于

constexpr duration() {}

这当然会留下类型的整数成员变量duration::rep未初始化?事实上,这不是标准行为duration这样默认构造的值are未初始化? (但我找不到明确说明这一点的参考文献。)

那么怎样才能= default构造函数duration be constexpr如果它使非静态成员变量未初始化?我缺少什么?


7.1.5 的constexpr说明符 [dcl.constexpr] 说:

的定义constexpr构造函数应满足 以下要求:

  • 该类不得有任何虚拟基类;
  • 对于默认的复制/移动构造函数,该类不应具有作为变体成员的可变子对象;
  • 每个参数类型应为文字类型;
  • 其函数体不应是函数 try 块;

另外,它的函数体要么是=delete,要么是 满足以下要求:

  • 其函数体应为 = default,或其函数体的复合语句应满足要求 对于 constexpr 函数的函数体;
  • 应初始化每个非变体非静态数据成员和基类子对象(12.6.2);
  • 如果该类是一个具有变体成员的联合体 (9.5),则应初始化其中的一个;
  • 如果该类是类似联合的类,但不是联合,则对于其每个具有变体成员的匿名联合成员,恰好是以下之一 它们应被初始化;
  • 对于非委托构造函数,选择初始化非静态数据成员和基类子对象的每个构造函数都应是 constexpr 构造函数;
  • 对于委托构造函数,目标构造函数应是 constexpr 构造函数。

简而言之,= default是 a 的有效定义constexpr只要满足上述其他要求即可使用默认构造函数。

那么这是如何工作的未初始化的建筑?

事实并非如此。

例如:

constexpr seconds x1{};

以上工作并初始化x1 to 0s。然而:

constexpr seconds x2;

error: default initialization of an object of const type 'const seconds'
       (aka 'const duration<long long>') without a user-provided default
        constructor
    constexpr seconds x2;
                      ^
                        {}
1 error generated.

所以要创建一个constexpr默认构造duration, 你必须零初始化它。还有= default实现允许零初始化{}.

完整的工作演示:

template <class Rep>
class my_duration
{
    Rep rep_;
public:
    constexpr my_duration() = default;
};


int
main()
{
    constexpr my_duration<int> x{};
}

有趣的侧边栏

我在写这个答案时学到了一些东西,并想分享:

我一直想知道为什么以下不起作用:

using Rep = int;

class my_duration
{
    Rep rep_;
public:
    constexpr my_duration() = default;
};


int
main()
{
    constexpr my_duration x{};
}

error: defaulted definition of default constructor is not constexpr
        constexpr my_duration() = default;
        ^

为什么使此类成为非模板会破坏constexpr默认构造函数?!

(Update:现在可以使用 C++20 进行编译)

然后我尝试了这个:

using Rep = int;

class my_duration
{
    Rep rep_;
public:
    my_duration() = default;  // removed constexpr
};


int
main()
{
    constexpr my_duration x{};
}

编译器再次喜欢它。

If there isn't already a CWG issue on this, there probably should be. The behavior seems a bit inconsistent. And this is probably just because we (the entire industry) are still learning about constexpr. Fixed in C++20.

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

std::chrono::duration::duration() 如何成为 constexpr? 的相关文章

  • 什么定义了类型的大小?

    ISO C 标准规定 sizeof char lt sizeof short lt sizeof int lt sizeof long 我在 BIT Linux mint 19 1 上使用 GCC 8 大小为long int is 8 我正
  • 我的 std::hash for std::tuples...有什么改进吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有些人可能已经注意到 std hash 不支持元组 所以我添加了一个重载 它看起来比我到目前为止看到的解决方案 更好 有人有进一步减少这段代码的
  • Visual Studios 2015 中的“恢复 NuGet 包”没有执行任何操作

    我将解决方案从 SVN 拉入 Visual Studios 2015 代码中的一些 使用 引用出现错误 因此我尝试在右键单击 解决方案 中的解决方案时运行 恢复 NuGet 包 选项探索者 这没有任何作用 我必须手动进入 nuget 管理器
  • 采用 std::vector 或 std::array 的模板函数

    我有一个函数 当前接受 2 个向量 其中可以包含任何普通的旧数据 template
  • getline 之后返回到文件开头

    所以我已经从文件中读取了所有行 while getline ifile line logic 其中 ifile 是 ifstream line 是字符串 我的问题是我现在想再次使用 getline 并且似乎无法返回到文件的开头 因为运行 c
  • 更新 Azure Blob 上的 LastModified

    我正在移植代码以使用 C 中的 Azure 存储 SDK 传统上 我称其为更新修改文件的上次写入 修改时间 File SetLastWriteTimeUtc fileName lastWriteTimeUtc 要更新 blob 的上次修改时
  • 预编译头和 Visual Studio

    有没有办法设置 Visual Studio 解决方案参数 以便它只创建预编译头而不构建整个解决方案 具体来说 它是一个巨大的 C 解决方案 本身有许多项目 谢谢 仅选择 pch 创建者源文件 通常是 stdafx cpp 然后编译该文件 C
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?

    我必须在 C DLL 中使用 VB COM DLL 我弄清楚了如何从 C DLL 访问 VB COM DLL 并且它可以工作 现在我遇到了一个问题 我必须使用隔离的 COM 免注册 COM 因为我无法在必须使用它的每台 PC 上注册 DLL
  • C# 中的抽象类和接口类有什么不同?

    C 中的抽象类和接口类有什么不同 An 接口不是类 它只是一个contract定义了public一个类的成员must实施 抽象类只是一个类 您从中可以cannot创建一个实例 通常您会使用它来定义一个基类 该基类定义了一些virtual方法
  • 查找方法不适用于 EF6.1 模拟

    我已经使用这些 msdn 指南设置了模拟 使用模拟框架进行测试 EF6 及以上 http msdn microsoft com en us data dn314429 var bsAc db BusAcnts FirstOrDefault
  • ASP.net WebForms - 在标记中使用 GetRouteUrl

    我一直在尝试弄清楚如何将路由功能与 ASP net 4 0 WebForms 一起使用 我将一条路线添加到我的路线集合中 void Application Start RegisterRoutes RouteTable Routes voi
  • 使用 OleDbCommand / OleDbDataAdapter 读取 CSV 文件

    我不明白为什么 但是当我使用 OleDbDataAdapter 或 OleDbCommand 读取 CSV 文件时 在这两种情况下 生成的数据结构良好 它识别文件头中的列 但行数据都是空字符串 我之前已经成功进行过多次 CSV 处理 因此我
  • 冒号在c中起什么作用?

    我在课堂上得到了这个例子 但我不确定它的作用 我知道冒号添加了一个位字段 但我仍然不确定这个问题 a b gt 0 3 1 运算符称为条件运算符 If b值为 gt 0 价值3被分配给a否则值1被分配给a 以 Kernighan Ritch
  • linq where 子句和 count 导致 null 异常

    除非 p School SchoolName 结果为 null 否则下面的代码将起作用 在这种情况下 它会导致 NullReferenceException if ExistingUsers Where p gt p StudentID i
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 如果仅使用第一个元素,是否必须为整个结构分配内存?

    我有一个结构 其中第一个元素被测试 并且根据其值 结构的其余部分将被读取或不会被读取 在第一个元素的值指示结构的其余部分不会被读取的情况下 我是否必须为整个结构或仅第一个元素分配足够的内存 struct element int x int
  • 'iter' 的名称查找已更改为新的 ISO 'for' 范围

    我正在尝试编译下面的两个文件 但从编译器收到错误消息 gcc 4 3 3 Linux 错误位于带有以下符号的行 LINE WITH ERROR 我做错了什么 我该怎么改变 路易斯 g c b h b cpp b cpp In functio
  • 为什么 C++ 标准没有将 sizeof(bool) 定义为 1?

    Size of char signed char and unsigned char由 C 标准本身定义为 1 个字节 我想知道为什么它没有定义sizeof bool also C 03 标准 5 3 3 1 说 sizeof char s

随机推荐