- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
给定以下代码:
struct f {
};
int main(){
constexpr f f1 ;
//const f f1 ; // This also has the same issue
//constexpr f f1 = {} ; //This works
}
clang 和 gcc 不同意它是否有效,clang 提供以下诊断 ( see it live ):
error: default initialization of an object of const type 'const f' without a user-provided default constructor
constexpr f f1 ;
^
{}
据我所知,f
是一种文字类型,它由隐式默认构造函数初始化,该构造函数应允许将其声明为 constexpr。谁是正确的?
请注意,如果我显式添加 constexpr 默认构造函数,clang 会接受 f1
的声明:
constexpr f() {} ;
答案是否改变为 f
不是聚合?
最佳答案
如果我们从 C++14 标准草案 7.1.5
[dcl.constexpr] 开始,我们可以发现对 constexpr 对象声明的要求是:
A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19).
那么f
是字面量类型吗?
3.9
部分 [basic.types] 说:
A type is a literal type if it is:
并涵盖以下项目符号中的类:
a class type (Clause 9) that has all of the following properties
- it has a trivial destructor,
- it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
- all of its non-static data members and base classes are of non-volatile literal types.
所以我们对第一个和第三个项目符号没问题。为了覆盖第二个项目符号,我们可以注意到 f
是一个聚合,但是如果我们稍微修改一下示例,例如如果 f
看起来像这样:
struct f {
private:
int x = 0 ;
} ;
这在 C++11 或 C++14 中都不是聚合,但问题仍然存在。然后我们需要证明它有一个 constexpr 构造函数。 f
是否有 constexpr 构造函数?
据我所知,12.1
[class.ctor] 说是:
[...] If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr. [...]
但不幸的是,8.5
部分要求我们有一个用户提供的构造函数,它说:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
所以看起来 clang 在这里是正确的,如果我们查看以下 clang 错误报告:"error: default initialization of an object of const type 'const Z' requires a user-provided default constructor" even when no constructor needed .因此,由于 defect report 253,clang 是基于他们对此缺乏支持。目前没有建议的措辞,它说(强调我的):
Paragraph 9 of 8.5 [dcl.init] says:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for an object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
如果 const POD 对象没有非静态数据成员怎么办?对于这种情况,这种措辞需要一个空的初始值设定项
[...]
类似的注释适用于非 POD const 对象,其所有非静态数据成员和基类子对象都具有默认构造函数。为什么要求此类对象的类具有用户声明的默认构造函数?
缺陷报告仍处于打开状态,但对其的最后评论是:
If the implicit default constructor initializes all subobjects, no initializer should be required.
还有注释:
This issue should be brought up again in light of constexpr constructors and non-static data member initializers.
请注意,自缺陷报告出现以来,8.5
部分中对 const 限定类型的约束有所改变。这是由于提议 N2762: Not so Trivial Issues with Trivial这是 C++11 之前的版本。
虽然缺陷报告仍然开放,但考虑到 constexpr 更改和非静态数据成员初始化器,它似乎不再是必要的限制。特别是考虑以下对 constexpr 构造函数的要求:
- every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);
关于c++ - 没有初始值设定项或显式默认构造函数的空类是否可用作 constexpr 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33813929/
我是一名优秀的程序员,十分优秀!