【发布时间】:2019-04-29 08:13:15
【问题描述】:
我想要一个类B,它有另一个类A 的3 个成员对象。 A 和 B 的构造函数都是 constexpr。 A - 包含在 B 中 - 不可复制且不可移动。此代码正确构建:
class A
{
public:
constexpr explicit A(int a) {}
A(const A&) = delete;
A(A&&) = delete;
};
class B
{
public:
constexpr B() :
a0{0},
a1{1},
a2{2}
{}
private:
A a0;
A a1;
A a2;
};
int main()
{
B b;
}
但是我真的很想将A 类型的3 个对象作为一个数组。如果我尝试这样的简单方法:
class A
{
public:
constexpr explicit A(int a) {}
A(const A&) = delete;
A(A&&) = delete;
};
class B
{
public:
constexpr B() :
a{A{1}, A{2}, A{3}}
{}
private:
A a[3];
};
int main()
{
B b;
}
构建失败:
$ g++ a.cpp
a.cpp: In constructor ‘constexpr B::B()’:
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
a{A{1}, A{2}, A{3}}
^
a.cpp:13:2: note: declared here
A(A&&) = delete;
^
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
a{A{1}, A{2}, A{3}}
^
a.cpp:13:2: note: declared here
A(A&&) = delete;
^
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
a{A{1}, A{2}, A{3}}
^
a.cpp:13:2: note: declared here
A(A&&) = delete;
^
a.cpp:28:2: error: member ‘B::a’ must be initialized by mem-initializer in ‘constexpr’ constructor
}
^
a.cpp:32:7: note: declared here
A a[3];
^
是否可以不使A可移动来解决?
编辑:
正如@rustyx 所建议的,我已经稍微更改了代码,它适用于 C++11 和 C++17(使用 explicit)。然而——像往常一样——真正的代码要复杂一些。假设A真的不可移动且不可复制,假设它有一个析构函数。
class A
{
public:
constexpr explicit A(int a) {}
~A() {}
A(const A&) = delete;
A(A&&) = delete;
};
class B
{
public:
constexpr B() :
a{A{1}, A{2}, A{3}}
{}
private:
A a[3];
};
int main()
{
B b;
}
即使使用 C++17 也会失败:
g++ a.cpp -std=c++17
a.cpp: In constructor ‘constexpr B::B()’:
a.cpp:14:22: error: use of deleted function ‘A::A(A&&)’
a{A{1}, A{2}, A{3}}
^
a.cpp:7:2: note: declared here
A(A&&) = delete;
^
a.cpp:14:22: error: non-constant array initialization
a{A{1}, A{2}, A{3}}
^
a.cpp:15:3: error: use of deleted function ‘A::A(A&&)’
{}
^
a.cpp:7:2: note: declared here
A(A&&) = delete;
^
如果A 的构造函数不是explicit,它也会失败。如果我删除析构函数,那么它就可以工作,但是如果析构函数必须在那里呢?这个特定的数组初始化问题是否有解决方案,或者我在这里不走运?
【问题讨论】:
-
您是否尝试将 C++17 标志添加到您的编译命令:
g++ -std=c++17 a.cpp?!使用 g++ 和 clang 为我工作。 -
@lubgr - 这个问题有 c++11 解决方案吗?
-
如果您可以在
A构造函数中删除explicit,则应该与a{ {1}, {2}, {3} }一起使用(也适用于C++11/C++14)。
标签: c++ arrays constructor initialization constexpr