强制编译器在未使用基 class 删除的复制构造函数定义的移动构造函数上发出错误
Force compiler to emit error on move constructor not defined with a base class deleted copy ctor
考虑一个基础 class 来防止像这样的复制构造和复制赋值:
class NonCopyable {
public:
NonCopyable() = default;
~NonCopyable() = default;
NonCopyable(NonCopyable const&) = delete;
NonCopyable& operator=(NonCopyable const&) = delete;
};
我们的开发人员现在可以包含此 class,并使用它来禁用继承的 classes 的复制,如下所示:
class CopyTest : public NonCopyable {
public:
CopyTest() {
std::cout << "copy test created" << std::endl;
}
~CopyTest() {
std::cout << "copy test deleted" << std::endl;
}
};
当我尝试使用 CopyTest
class:
CopyTest ct, ct1(ct);
或
CopyTest ct;
CopyTest ct1 = ct2;
编译器发出错误:use of deleted function xxx
(其中 xxx 是我删除的复制构造函数或复制运算符)
然后,如果我想 std::move
一个 CopyTest
对象:
CopyTest ct;
CopyTest ct1 = std::move(ct);
编译器发出相同的错误(使用已删除的函数 xxx - 其中 xxx 仍然是我的复制构造函数或赋值运算符)。
如果我没记错的话,那是因为开发者没有定义正确的ctor/assignement操作符。
是否可以强制编译器告诉CopyTest
class的开发者这里的走法错误是因为他没有定义正确的走法ctor/assignement 运算符,而不是因为在 class?
基础上删除了复制 ctor/assignement 运算符
平台:
Debian 9
海湾合作委员会 6.3.0
编译标志:
-fpermissive -ggdb -std=c++11
添加
NonCopyable(NonCopyable &&) = delete;
NonCopyable& operator=(NonCopyable &&) = delete;
现在抱怨基础 class 移动 ctor 被删除。
正式地说,隐式生成的走法ctor/assignment在基classNonCopyable
本身中被定义为"deleted"。 "deleted" 移动 ctor/assignment 只是被重载决议忽略(而不是在严格意义上被删除)。由于 NonCopyable
不可复制且不可移动,因此任何子 class 都将其隐式(和 =default)复制和移动操作定义为已删除。
在严格的 iso c++ 下,您的设计具有所需的语义,但不幸的是,大多数编译器并不严格执行所谓的 5 规则 ,而仅执行 的一个子集=19=]隐式删除 规则。例如,让用户为 class 声明析构函数意味着将删除所有复制和移动操作的隐式(和 =default)定义,但我不知道编译器无法编译或发出当隐式声明的复制构造函数将被 ODR 用于此类 class.
时发出警告
我看到了这个错误报告 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58407#c16。它表明编译器可能会开始强制执行或警告违反 五次 规则。
考虑一个基础 class 来防止像这样的复制构造和复制赋值:
class NonCopyable {
public:
NonCopyable() = default;
~NonCopyable() = default;
NonCopyable(NonCopyable const&) = delete;
NonCopyable& operator=(NonCopyable const&) = delete;
};
我们的开发人员现在可以包含此 class,并使用它来禁用继承的 classes 的复制,如下所示:
class CopyTest : public NonCopyable {
public:
CopyTest() {
std::cout << "copy test created" << std::endl;
}
~CopyTest() {
std::cout << "copy test deleted" << std::endl;
}
};
当我尝试使用 CopyTest
class:
CopyTest ct, ct1(ct);
或
CopyTest ct;
CopyTest ct1 = ct2;
编译器发出错误:use of deleted function xxx
(其中 xxx 是我删除的复制构造函数或复制运算符)
然后,如果我想 std::move
一个 CopyTest
对象:
CopyTest ct;
CopyTest ct1 = std::move(ct);
编译器发出相同的错误(使用已删除的函数 xxx - 其中 xxx 仍然是我的复制构造函数或赋值运算符)。
如果我没记错的话,那是因为开发者没有定义正确的ctor/assignement操作符。
是否可以强制编译器告诉CopyTest
class的开发者这里的走法错误是因为他没有定义正确的走法ctor/assignement 运算符,而不是因为在 class?
平台:
Debian 9
海湾合作委员会 6.3.0
编译标志:
-fpermissive -ggdb -std=c++11
添加
NonCopyable(NonCopyable &&) = delete;
NonCopyable& operator=(NonCopyable &&) = delete;
现在抱怨基础 class 移动 ctor 被删除。
正式地说,隐式生成的走法ctor/assignment在基classNonCopyable
本身中被定义为"deleted"。 "deleted" 移动 ctor/assignment 只是被重载决议忽略(而不是在严格意义上被删除)。由于 NonCopyable
不可复制且不可移动,因此任何子 class 都将其隐式(和 =default)复制和移动操作定义为已删除。
在严格的 iso c++ 下,您的设计具有所需的语义,但不幸的是,大多数编译器并不严格执行所谓的 5 规则 ,而仅执行 的一个子集=19=]隐式删除 规则。例如,让用户为 class 声明析构函数意味着将删除所有复制和移动操作的隐式(和 =default)定义,但我不知道编译器无法编译或发出当隐式声明的复制构造函数将被 ODR 用于此类 class.
时发出警告我看到了这个错误报告 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58407#c16。它表明编译器可能会开始强制执行或警告违反 五次 规则。