强制编译器在未使用基 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。它表明编译器可能会开始强制执行或警告违反 五次 规则。