CLion (2023.1.2) использует clang-tidy v17 для моего проекта. Он жалуется на то, что я передаю std::experimental::optional
(из С++ 14) по значению, а не по ссылке. Это кажется мне вопиющим ... как я могу увеличить «порог веса объекта» для выявления аккуратных жалоб на копирование?
Точное описание проблемы:
Clang-Tidy: параметр «независимо» копируется для каждого вызова, но используется только как константная ссылка; подумайте о том, чтобы сделать его константной ссылкой
Примечание. В отличие от этого вопроса, я хочу изменить порог clang-tidy, а не внести в белый список определенную строку кода или определенный тип.
@TedLyngmo: Может быть, это особенность С++ 14. Я ограничу вопрос. Кроме того, размер имеет смысл, потому что он должен быть больше 4, чтобы вместить nullopt
, а размер 5 или 6 был бы странным и проблематичным с точки зрения производительности.
Ага. Что ж, я понимаю это при использовании std::experimental::optional
как в режиме C++14, так и в режиме C++20, а использование std::optional
в C++20 не вызывает таких жалоб.
Я также пытаюсь понять код clang-tidy. Не могу найти способ отключить его с помощью ограничения веса, но это не простой для чтения код. В нем говорится: «Не предлагать исправления, когда: 1. ParmVarDecl находится в макросе, поскольку мы не можем правильно разместить их, 2. функция является виртуальной, поскольку она может нарушить переопределение, 3. на функцию ссылаются вне выражения вызова в пределах единица компиляции, поскольку изменение подписи может привести к ошибкам сборки, 4. функция является основным шаблоном или явной специализацией шаблона», но не упоминает порог размера или что-то подобное.
Приведенные выше комментарии взяты из clang-tidy/performance/UnnecessaryValueParamCheck.cpp кстати
@TedLyngmo: Итак, похоже, вы говорите, что такого ограничения нет, и, возможно, мне следует сообщить об ошибке. Но - вы заметили, по какому критерию они предупреждают? Я тоже завтра пойду читать.
Да, это все, что я понял, прежде чем мне пришлось самому лечь спать :-) Приятно, что ecatmur нашел причину, и, возможно, отчет об ошибке / запрос на улучшение были бы уместны.
Clang-tidy check «performance-unnecessary-value-param» ищет типы аргументов, которые удовлетворяют предикату «isExpensiveToCopy», который является довольно простым тестом для нетривиальных типов:
return !Type.isTriviallyCopyableType(Context) &&
!classHasTrivialCopyAndDestroy(Type) &&
!hasDeletedCopyConstructor(Type) &&
!Type->isObjCLifetimeType();
Это разумно в вашем случае, потому что TS std::experimental::Optional не распространяет тривиальную возможность копирования из своего параметра, тогда как std::Optional делает:
void f(std::optional<int>) {} // does not warn, because:
static_assert(std::is_trivially_copyable_v<std::optional<int>>);
void f(std::experimental::optional<int>) {} // warns, because:
static_assert(not std::is_trivially_copyable_v<std::experimental::optional<int>>);
Тест несколько наивен; оптимизатор может исключить конструктор копирования std::experimental::optional<int>
. Но порога «веса» нет. Действительно, проверка не предупреждает о std::array<int, 1024>
:
void f(std::array<int, 1024>) {} // does not warn, because:
static_assert(std::is_trivially_copyable_v<std::array<int, 1024>>);
Демо .
У меня есть только clang-tidy 16, и он не жалуется на меня. Это новое в v17? Кстати,
sizeof(std::optional<unsigned>)
на моей машине стоит8
.