统一支撑数组初始化的保证复制省略——自 C++17 以来,这不应该是强制性的吗?
Guaranteed copy elision for uniform braced array initialization - Shouldn't this be mandatory since C++17?
据我对新规则的理解是正确的
https://en.cppreference.com/w/cpp/language/copy_elision
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
此代码应针对符合 C++17 标准的编译器进行编译
struct NonTrivialClass
{
~NonTrivialClass( ){ }
};
class MainNonTrivialClass
{
public:
MainNonTrivialClass(int t) : m_simpleTypeMember(t) { }
virtual void makeMySelfNonTrivial() {}
MainNonTrivialClass( const MainNonTrivialClass& other) = delete;
MainNonTrivialClass& operator=( const MainNonTrivialClass& other) = delete;
MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
MainNonTrivialClass& operator=(MainNonTrivialClass&& other) = delete;
NonTrivialClass m_nontrivialMember;
int m_simpleTypeMember;
};
class ArrayContainer
{
public:
ArrayContainer() : m_array{{1}, {2} } {}
private:
MainNonTrivialClass m_array[2];
};
int main()
{
ArrayContainer accContainer;
}
但是带有 -std=c++17 -O2 -Wall -pedantic 的 gcc 9.1.0 说(完全符合预 C++17 的预期)
main.cpp: In constructor 'ArrayContainer::ArrayContainer()':
main.cpp:25:39: error: use of deleted function 'MainNonTrivialClass::MainNonTrivialClass(MainNonTrivialClass&&)'
25 | ArrayContainer() : m_array{{1}, {2} } {}
| ^
main.cpp:15:3: note: declared here
15 | MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
以这种方式进行的数组统一初始化被定义为按元素复制初始化(?),应该会导致复制省略,所以我不太明白,这里到底发生了什么。旧的 C++17 之前的规则似乎适用于此。进一步的好奇是,如果我从我的 MainNonTrivialClass 中删除 m_nontrivialMember,相同的代码编译正常,但它不应该导致相同的编译错误,因为非复制省略案例强制存在相应的 copy/move 构造函数总是?
这也应该适用于 C++17 之前的版本,其中此语法是直接初始化的。参见 How to initialize array of classes with deleted copy constructor (C++11) which refers to GCC bug 63707。
据我对新规则的理解是正确的
https://en.cppreference.com/w/cpp/language/copy_elision
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
此代码应针对符合 C++17 标准的编译器进行编译
struct NonTrivialClass
{
~NonTrivialClass( ){ }
};
class MainNonTrivialClass
{
public:
MainNonTrivialClass(int t) : m_simpleTypeMember(t) { }
virtual void makeMySelfNonTrivial() {}
MainNonTrivialClass( const MainNonTrivialClass& other) = delete;
MainNonTrivialClass& operator=( const MainNonTrivialClass& other) = delete;
MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
MainNonTrivialClass& operator=(MainNonTrivialClass&& other) = delete;
NonTrivialClass m_nontrivialMember;
int m_simpleTypeMember;
};
class ArrayContainer
{
public:
ArrayContainer() : m_array{{1}, {2} } {}
private:
MainNonTrivialClass m_array[2];
};
int main()
{
ArrayContainer accContainer;
}
但是带有 -std=c++17 -O2 -Wall -pedantic 的 gcc 9.1.0 说(完全符合预 C++17 的预期)
main.cpp: In constructor 'ArrayContainer::ArrayContainer()':
main.cpp:25:39: error: use of deleted function 'MainNonTrivialClass::MainNonTrivialClass(MainNonTrivialClass&&)'
25 | ArrayContainer() : m_array{{1}, {2} } {}
| ^
main.cpp:15:3: note: declared here
15 | MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
以这种方式进行的数组统一初始化被定义为按元素复制初始化(?),应该会导致复制省略,所以我不太明白,这里到底发生了什么。旧的 C++17 之前的规则似乎适用于此。进一步的好奇是,如果我从我的 MainNonTrivialClass 中删除 m_nontrivialMember,相同的代码编译正常,但它不应该导致相同的编译错误,因为非复制省略案例强制存在相应的 copy/move 构造函数总是?
这也应该适用于 C++17 之前的版本,其中此语法是直接初始化的。参见 How to initialize array of classes with deleted copy constructor (C++11) which refers to GCC bug 63707。