У меня есть структура с этими специальными функциями-членами:
struct MyStruct {
MyStruct(MyStruct& other) = delete;
MyStruct(MyStruct&& other) = default;
explicit MyStruct(int num) noexcept(false);
explicit MyStruct(MyOtherStructType&& other_type);
~MyStruct();
auto operator=(MyStruct&& other) noexcept(false) -> MyStruct&;
}
Clang Tidy говорит:
Class 'MyStruct' defines a non-default destructor, a copy constructor, a move
constructor and a move assignment operator but does not define a copy assignment
operator
Но из-за ворса hicpp-special-member-functions/cppcoreguidelines-special-member-functions
я думал, что удалил конструктор копирования? Я что-нибудь пропустил? Ворс неправильный?
Да, меня это не волнует, я хочу знать, почему он думает, что у меня есть конструктор копирования.
У вас есть один. Он удален, а значит ошибка в его использовании, но он есть.
Это может сбить с толку, поскольку аргумент вашего конструктора копирования не является константным, что нетипично.
@RaymondChen он там, как указано в коде, как недоступный? Мне это кажется странным определением «определенного».
«Определено как удаленное» отличается от «не определено».
Правило пяти применяется ко всем другим специальным функциям-членам после того, как вы явно объявляете любую специальную функцию-член, а не только тогда, когда вы предоставляете для нее собственное определение. Определение функции как удаленной по-прежнему учитывается.
Обратите внимание, что определение функции как удаленной — это не то же самое, что отсутствие объявления функции вообще (неявно или явно). Функция, определенная как удаленная, по-прежнему объявляется и участвует в разрешении перегрузки как обычно. Единственное значение, которое это имеет, заключается в том, что если разрешение перегрузки выберет удаленную функцию, то разрешение перегрузки будет считаться неправильно сформированным.
Причина, по которой правило также должно применяться при удалении конструктора копирования, заключается в том, что удаление конструктора копирования не препятствует неявному определению оператора присваивания копирования.
Но если вы явно удалили конструктор копирования, то вполне вероятно, что ваш тип также не должен иметь семантику копирования по умолчанию при назначении. Правило пяти гарантирует, что вы не забудете объявить правильную семантику для оператора присваивания копии, который, если вы хотите, можно объявить значениями по умолчанию для компилятора, определив перегрузку как = default
.
Как бы то ни было, написание
MyStruct x(1);
MyStruct y = x;
имеет неправильную форму, но
MyStruct x(1);
MyStruct y(2);
y = x;
будет компилироваться с поведением копирования по умолчанию, сгенерированным компилятором, что, вероятно, неверно для вашего типа, если вы удалили конструктор копирования.
Кроме того, конструктор копирования или оператор присваивания копирования должен принимать свой параметр в качестве ссылки const
. Несоблюдение этого соглашения вызовет у вас проблемы. Поскольку удаленная перегрузка по-прежнему участвует в разрешении перегрузки, по-прежнему имеет значение, использует ли она const
.
Он жалуется на оператор присваивания копирования, который вы не определили.