Заставить компилятор выдавать ошибку при перемещении конструктора, не определенного с удаленным копированием базового класса 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. Это предполагает, что компиляторы, вероятно, начнут применять или предупреждать о нарушении правила пяти нарушений.