Заставить компилятор выдавать ошибку при перемещении конструктора, не определенного с удаленным копированием базового класса - PullRequest
0 голосов
/ 12 декабря 2018

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

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 a CopyTest объект:

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

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

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

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

Платформа:

Debian 9

GCC 6.3.0

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

-fpermissive -ggdb -std = c ++11

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

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

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

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

0 голосов
/ 12 декабря 2018

add

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

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

...