Этот код вызывает предупреждение в clang tidy:
Класс «Locker» определяет деструктор не по умолчанию, но не определяет конструктор копирования, оператор присваивания копии, конструктор перемещения или оператор присваивания перемещенияclang-tidy(cppcoreguidelines-special-member-functions)
Это обновленная структура, согласно комментариям:
struct Locker
{
std::binary_semaphore *sem = nullptr;
// ----------------------------------
// Methods
// ----------------------------------
auto try_lock(std::binary_semaphore &sem_, u32 time_in_seconds = 1) -> bool;
auto manual_release() -> void;
// ----------------------------------
// Deleted
// ----------------------------------
Locker(Locker &) = delete;
Locker(Locker &&) = delete;
Locker(std::binary_semaphore &&sem_) noexcept = delete;
Locker(std::binary_semaphore &sem_) noexcept = delete;
Locker(std::binary_semaphore *sem_) noexcept = delete;
Locker() noexcept = default;
auto operator=(std::binary_semaphore &sem_) noexcept -> Locker & = delete;
auto operator=(std::binary_semaphore &&sem_) noexcept -> Locker & = delete;
auto operator=(std::binary_semaphore *sem_) noexcept -> Locker & = delete;
// ----------------------------------
// Destructor
// ----------------------------------
~Locker()
{
manual_release();
}
};
Мне не нужны никакие конструкторы, но мне нужен конкретный деструктор. у нас есть способ попробовать блокировку, а деструктор просто снимает блокировку, убедившись, что все в порядке.
Обратите внимание, что GCC 12.2 с
-Wall -Wextra -pedantic -pedantic-errors -Werror -Wuninitialized -Wtrivial-auto-var-init -Wshadow -Wnormalized -Wno-error=comment
даже не мешает.
Как подавить это предупреждение?
Спасибо!
Ниже приведена ссылка на Godbolt, чтобы воспроизвести ситуацию, может ли кто-нибудь исправить мой код и поделиться ссылкой здесь? Ссылка на проблему со структурой clang-tidy
@463035818_is_not_a_number подойдет прямо сейчас
@ 463035818_is_not_a_number : значение по умолчанию повышается: только специальные функции-члены и операторы сравнения могут быть заданы по умолчаниюclang (default_special_members)
Конструктор и оператор по значению устарели, на них уже распространяется ссылка на константу — при реализации обоих вы столкнетесь с двусмысленностью.
@Aconcagua: я улучшил код в соответствии с вашим замечанием; Я отражу это в посте
тогда вы, должно быть, сделали опечатку. Предупреждение жалуется только на те специальные элементы, для которых можно использовать значения по умолчанию.
Конструктор ссылки на R-значение, вероятно, не имеет смысла, даже если вы реализуете другие, по-видимому, Locker
в любом случае не становится владельцем объекта.
@Aconcague Я имею в виду свое предложение =default
специальным членам, а не подавлению предупреждения, а не конструкторам, уже присутствующим в коде.
Теперь вопрос в том, как вы хотели бы обрабатывать копирование/назначение. Должен ли сам Locker
копироваться? В настоящее время вы разрешаете неявные конструкторы перемещения и копирования, хотя неясно, имеет ли это смысл, учитывая удерживаемый семафор, и деструктор, вероятно, освободит его, пока конструктор получит его.
@ 463035818_is_not_a_number А, понятно. Тогда ответ автора вопроса был отвлекающим маневром ;)
Если я удалю деструктор, Clang больше не будет жаловаться
Я думаю, что решающим моментом здесь является то, что правило 5 важно не только для аккуратного лязга. Это важно для людей, читающих ваш код. Если вы реализуете один, вы должны предоставить и другие. Если вы этого не сделаете, то, вероятно, в вашем коде есть ошибка, и даже если это не так, это сбивает с толку, потому что ожидается правило 5. Правило настолько важно, что я бы предпочел добавить какой-нибудь код, который ничего не делает, например, избыточный special_member() = delete;
или speical_member() = default;
. Если вы придерживаетесь правила 5, то также исчезнет предупреждение о лязгах.
@Aconcagua: Locker нельзя скопировать, он просто берет указатель на семафор с помощью метода try_lock (здесь не показан). затем, когда область достигает конца, она автоматически освобождает семафор. Больше ничего
если нельзя скопировать, то почему нет Locker(const Locker&) = delete;
?
В значительной степени то, что я предположил из именования, факта хранения семафора и вывода деструктора;) Тогда вам действительно нужно Locker(Locker const&) = delete
избавиться от конструктора копирования по умолчанию. Это само по себе уже удалит конструктор перемещения, хотя может иметь смысл действительно иметь возможность перемещать объекты этого типа — тогда вы бы определили такой — убедившись, что указатель перемещаемого объекта снова установлен на nullptr
.
Добавление шкафчика (const Locker &) = удалить; и Locker(const Locker &&) = удалить; предупреждение все еще здесь
const
Ссылки на r-значения довольно бессмысленны, если не считать некоторых очень специфических особых случаев — конструктор перемещения по умолчанию принимает неконстантные Locker&&
— хотя при его удалении в любом случае это не имеет большого значения.
Locker(const Locker &&)
неверно, удалите const
.
Я обновил структуру в соответствии с вашими комментариями
Вам также нужно сделать то же самое с назначением копирования/перемещения.
Вам все еще нужно сделать то же самое для оператора присваивания: Locker& operator=(Locker const&) = delete
.
И вам не нужно удалять никакие нестандартные конструкторы — если вы их просто не определите, они не будут существовать. Итак, все, что вам действительно нужно — кроме удаленных стандартных конструкторов/присваиваний копирования/перемещения (тех, которые принимают какую-то ссылку на Locker
), — это конструктор, принимающий ссылку или указатель (в зависимости от того, что вы считаете более значимым, я лично склоняюсь к ссылке). в то время как вы просто можете удалить все остальные, принимающие любую константную ссылку на семафор или указатель.
Я удалил все константы, но все равно получил предупреждение. Позвольте мне обновить в моем посте
@Aconcagua позвольте мне попробовать это
Резюме: все, что вам действительно нужно, это: Locker(std::binary_semaphore& s) : sem(&s) { } Locker(Locker const&) = delete; Locker& operator=(Locker const&) = delete
- удаление конструктора перемещения и присваивания не является обязательным, они все равно будут удалены (путем определения, установки по умолчанию или удаления варианта копирования), но, конечно, вы все равно можете добавить их для большей ясности. ..
Любая комбинация все равно приведет к предупреждению. Это сводит меня с ума
Вы также удалили const
из конструктора/назначения копирования — обратите внимание: ссылка на l-значение -> const -> копировать, ссылка на r-значение -> неконстантное -> перемещение!
Ко всему добавил ссылку на компилятор godbolt, все варианты с clang tidy и тд, может кто поправит мой код и поделится ссылкой?
Смотрите фиксированный вариант здесь.
Демонстрация передвижного шкафчика — если это кажется вам значимым. Возможно, это не очень актуально здесь, но вы можете вспомнить шаблон для других целей в будущем;)
о, круто, я не знал, что Godbolt может звенеть аккуратно, это сильно упрощает задачу :)
@Aconcagua: большое спасибо, жаль, что я не могу проголосовать
В основном с помощью Аконкагуа и н.м. мы выяснили, в чем заключалось ваше заблуждение.
У этого неправильная подпись:
Locker( Locker &) = delete;
Конструктор копирования принимает const Locker&
. И вы не delete
задание. Это пятёрка:
Locker(const Locker &) = delete;
Locker(Locker &&) = delete;
Locker& operator=(const Locker&) = delete;
Locker& operator=(Locker&&) = delete;
~Locker() {
std::cout << "";
}
Если вы явно объявите их все, предупреждение должно исчезнуть: https://godbolt.org/z/eP8TrE9b1
Большое спасибо! То же самое для Аконкагуа, но я не могу проголосовать
@LeXav Я добавил несколько кредитов к ответу. Я в основном просто писал вещи из комментариев в ответ
Спасибо, хороший ход с твоей стороны
вместо подавления я бы определил их. Может быть,
= default
уже достаточно, вы пробовали это?