Rya*_*ing 9 c++ constexpr c++11 c++14
我有一个带有constexpr值构造函数的类,但没有复制或移动ctor
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
};
int main() {
constexpr C arr[] = {1, 2};
}
Run Code Online (Sandbox Code Playgroud)
我发现这段代码不起作用,因为它实际上是试图使用移动构造函数C而不是值构造函数来构造.一个问题是我希望这个对象不可移动(出于测试目的),但我认为"好吧,好吧,我会添加一个移动构造函数."
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
C& operator=(C&&) = delete;
C(C&&) { /*something*/ } // added, assume this must be non trivial
};
Run Code Online (Sandbox Code Playgroud)
好的,现在它使用移动构造函数,一切都在gcc下运行但是当我使用clang时,它会抱怨因为移动构造函数没有标记constexpr
error: constexpr variable 'arr' must be initialized by a constant expression
constexpr C arr[] = {1, 2};
Run Code Online (Sandbox Code Playgroud)
如果我标记移动构造函数constexpr它在gcc和clang下工作,但问题是我想在移动构造函数中有代码,如果它运行,并且constexpr构造函数必须有空体.(我在移动ctor中使用代码的原因不值得进入).
那么谁在这里?我的倾向是clang对于拒绝代码是正确的.
注意
它使用初始化列表和不可复制的不可移动对象进行编译,如下所示:
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
C& operator=(C&&) = delete;
C(C&&) = delete;
};
int main() {
constexpr C arr[] = {{1}, {2}};
}
Run Code Online (Sandbox Code Playgroud)
我主要担心的是上面哪个编译器是正确的.
\n\n\n那么谁在这里呢?
\n
Clang 拒绝代码是正确的。[expr.const]/2:
\n\n\n\n\n条件表达式
\n\ne是核心常量表达式,除非\n 的计算e遵循抽象机的规则\n (1.9),将计算以下表达式之一:\n
\n- \n
constexpr对文字类、函数的构造函数以外的函数的调用constexpr,或普通析构函数的隐式调用\n (12.4)
显然你的移动构造函数不是constexpr构造函数 - [dcl.constexpr]/2
\n\n\n类似地,
\nconstexpr构造函数声明中使用的说明符将该构造函数声明为constexpr构造函数。
对象初始值设定项的要求constexpr在 [dcl.constexpr]/9 中:
\n\n\n[\xe2\x80\xa6] 出现在其初始值设定项中的每个完整表达式都应是常量表达式。[注意:用于转换初始化表达式的每个隐式转换和用于初始化的每个构造函数调用都是此类完整表达式的一部分。\xe2\x80\x94尾注\n ]
\n
最后,通过使用相应的初始化子句 - [dcl.init] 复制初始化数组元素来调用移动构造函数:
\n\n\n\n\n否则(即,对于其余的复制初始化情况),可以从源类型转换为目标类型或(当使用转换函数时)转换为其派生类的用户定义转换序列为如 13.3.1.4 中所述枚举,并通过重载决策 (13.3) 选择最好的一个。如果转换无法完成或不明确,则初始化格式错误。使用初始值设定项\n 表达式作为其参数来调用所选函数;如果该函数是构造函数,则调用会初始化目标类型的 cv 未限定版本的临时版本。临时值是纯右值。然后,根据上述规则,调用的结果(对于构造函数情况来说是临时的)用于直接初始化作为复制初始化目标的对象。
\n
在第二个示例中,应用了复制列表初始化-并且没有引入临时值。
\n\n顺便说一句:即使没有提供任何警告标志, GCC 4.9 也不会编译上述内容。
\n