试图理解C++14中的[expr.const]

Trying to understand [expr.const] in C++14

本文关键字:expr const 中的 C++14      更新时间:2023-10-16

在C++14标准中,它是否禁止以下对象a声明

class A{ int i = 1; public: A():i{1}{} };
int main()
{
    constexpr A a{};
}

参见的实例

请注意,我强调了单词声明,因为我不认为§5.19[expr.const]p2中的要点(2.7.2)或(2.7.3)是这个问题的答案。

[dcl.constexpr]p9:

对象声明中使用的constexpr说明符将对象声明为const。此类对象应具有文字类型并应进行初始化。如果它是由构造函数调用初始化的,该调用应为常量表达式(5.19)。[…]

您现在遇到的错误是因为您的类型不是文字类型。您的类型不是文字类型,因为它有自定义构造函数,但没有任何constexpr构造函数。错误消息中的措辞对确切的要求相当清楚。

如果添加constexpr构造函数(但不是默认构造函数),则错误消息将更改:

class A{ int i = 1; public: A():i{1}{} constexpr A(int){} };
int main()
{
    constexpr A a{};
}

现在错误信息变为

错误:调用非常量表达式"A::A()"constexpr A A{};

这是我加粗的第二部分:它不是必须是常量表达式的初始化程序。你是对的,你的初始化程序根本不是一个表达式。构造函数调用必须是一个常量表达式,尽管它在源代码中没有显式表达,但它仍然是一个表达式。这一点在[expr.const]中有明确的说明:

  • 对文字类的constexpr构造函数以外的函数的调用、constexpr函数的调用,或对平凡析构函数(12.4)的隐式调用[…]

你在问题中已经提到了这一点。

好吧,您的默认构造函数不是constexpr。因此,不能创建默认构造的constexpr对象。