Заставить компилятор выдавать ошибку при перемещении конструктора, не определенного с удаленным копированием базового класса ctor

Рассмотрим базовый класс, который предотвращает создание копии и назначение копирования следующим образом:

class NonCopyable {
    public:
        NonCopyable() = default;
        ~NonCopyable() = default;

        NonCopyable(NonCopyable const&)                 = delete;
        NonCopyable& operator=(NonCopyable const&)      = delete;
};

Теперь наши разработчики могут включить этот класс и использовать его для отключения копирования для унаследованных классов, например:

class CopyTest : public NonCopyable {
    public:
        CopyTest() {
            std::cout << "copy test created" << std::endl;
        }

        ~CopyTest() {
            std::cout << "copy test deleted" << std::endl;
        }
};

Когда я пытаюсь использовать CopyTest учебный класс:

CopyTest ct, ct1(ct);

или же

CopyTest ct;
CopyTest ct1 = ct2;

Компилятор выдает ошибку: use of deleted function xxx (где xxx - мой удаленный экземпляр ctor или оператор копирования)

Тогда, если я хочу std::move CopyTest объект:

CopyTest ct;
CopyTest ct1 = std::move(ct);

Компилятор выдает ту же ошибку (использование удаленной функции xxx - где xxx остается моим оператором копирования или оператором присваивания).

Если я правильно напомню, это потому, что разработчик не определил правильный оператор ctor/assignment move.

Можно ли заставить компилятор сообщить разработчику о CopyTest класс, что ошибка перемещения здесь, потому что он не определил правильный оператор ctor/assignement перемещения, а не потому, что оператор ctor/assignement копирования удален в базовом классе?

Платформа:

Debian 9

GCC 6.3.0

Флаги компиляции:

-fpermissive -ggdb -std = C++11

2 ответа

Решение

Добавлять

    NonCopyable(NonCopyable &&)                 = delete;
    NonCopyable& operator=(NonCopyable &&)      = delete;

теперь жалуется на удаление ctor базового класса.

Формально говоря, неявно сгенерированный ход / назначение перемещения определяется как "удаленный" в базовом классе. NonCopyable сам. "Удаленный" ход / назначение перемещения просто игнорируется разрешением перегрузки (вместо удаления в строгом смысле). поскольку NonCopyable не копируется и не может быть перемещен, любой подкласс будет иметь свои неявные (и = по умолчанию) операции копирования и перемещения, которые будут определены как удаленные.

В строгом стандарте iso C++ ваш дизайн имеет требуемую семантику, но, к сожалению, большинство компиляторов не строго соблюдают так называемое правило пяти, но применяют только подмножество неявно удаленного правила. Например, если пользователь объявил деструктор для класса, это означает, что неявные (и = по умолчанию) определения всех операций копирования и перемещения будут удалены, но я не знаю компилятора, который не может скомпилировать или выдать предупреждение, когда неявно объявленный конструктор копирования будет ODR, используемым для такого класса.

Я наткнулся на этот отчет об ошибке https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58407. Это предполагает, что компиляторы, вероятно, начнут применять или предупреждать о нарушении правила пяти нарушений.

Другие вопросы по тегам