以下代码使用GCC和某些版本的Clang编译某些版本(请参阅下面的版本)。
struct my_struct {};
int main(int argc, char** argv) {
const my_struct my_object;
return 0;
};
编译:{{1}}和g++ clang_error.cpp
。我在 4.8.4 和clang ++在3.6.0时使用g ++。
错误消息是:
clang++ clang_error.cpp
使用 Compiler Explorer here,我可以看到GCC高达4.5.4受到影响。 Clang受到的影响高达3.9.0。
我的问题是: C ++标准对此有何看法?理想情况下,我关心的是C ++ 14,但我并不挑剔。
以上示例代码是否符合标准?
我在C ++ 14的Draft N3797中找到了以下内容。
§7.1.6.1cv-qualifiers [dcl.type.cv]
2 [注意:声明变量const可以影响其链接(7.1.1)及其在常量表达式(5.19)中的可用性。 如8.5中所述,const限定类型的对象或子对象的定义必须指定初始化器 或接受默认初始化。 - 结束注释]§8.5 7默认初始化T类型的对象意味着:
- 如果T是(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(12.1)(和 如果T没有默认构造函数,则初始化是错误的,或者重载解析(13.3)导致 模糊性或在初始化上下文中删除或无法访问的函数中;; - 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,不执行初始化。
答案 0 :(得分:4)
C ++标准对此有何看法?
以上示例代码是否符合标准?
在C ++ 14中,它不符合要求:
n4431(2015)标准草案[dcl.init] / 7:
如果程序要求对const限定类型的对象进行默认初始化 Ť , Ť 应为班级类型 使用用户提供的默认构造函数。
my_struct
没有用户提供的默认构造函数,因此您不应默认初始化。
但是,一些较新的编译器似乎选择放宽规则,可能是因为它受到缺陷报告的影响:DR 253。
即将推出的标准改变了措辞:
Current(2017)标准草案[dcl.init] / 7:
如果T的默认初始化将调用用户提供的T构造函数(不是从基类继承)或者
,则类类型T是const-default-constructible(7.4)T的每个直接非变量非静态数据成员M都有一个默认成员初始化器,或者,如果M是类X(或其数组),则X是const-default-constructible,
(7.5)如果T是与至少一个非静态数据成员的并集,则只有一个变体成员具有默认成员初始值设定项,
(7.6)如果T不是联合,对于每个具有至少一个非静态数据成员(如果有)的匿名联合成员,只有一个非静态数据成员具有默认成员初始化程序,并且
(7.7)每个可能构造的T的基类都是const-default-constructible。
如果程序要求对const限定类型T的对象进行默认初始化,则T应为const-default-constructible类类型或其数组。
措辞对我来说有点模棱两可,但我认为由于my_struct
没有违反7.4的成员(并且不是工会,所以7.5不适用,没有工会成员所以7.6不适用并且没有基础,因此7.7不适用),它是const-default-constructible,因此该示例将是符合的。