Clang-tidy check cppcoreguidelines-avoid-const-or-ref-data-members предупреждает о const квалифицированных членах, ссылаясь на Основные рекомендации C++ C.12 Не делайте элементы данных постоянными или ссылками в копируемом или перемещаемом типе, см.
и
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-constref
Enforcement Пометить элемент данных, который является const, & или && в типе, который имеет любую операцию копирования или перемещения.
Однако похоже, что указанная проверка Clang-Tidy применяется и к типам, которые не имеют операций копирования или перемещения. Имеет ли это смысл? Я имею в виду, что const неявно сделает тип недоступным для копирования. Но если тип все равно не копируется, потому что конструктор копирования и оператор присваивания были удалены явно, следует ли по-прежнему избегать члена const?
Я спрашиваю, потому что я заметил указанное предупреждение для некопируемого класса с удаленным конструктором копирования и оператором присваивания, содержащим некоторые privatecondition_variable (по этой причине он не копируется) плюс некоторый privateconst член, установленный только в конструкторе ( повод для предупреждения).
class Foo // simplified
{
public:
explicit Foo(int someSetup) : someSetup{someSetup} {}
~Foo() = default;
Foo(const Foo&) = delete;
Foo(Foo&&) = delete;
Foo& operator=(const Foo&) = delete;
Foo& operator=(Foo&&) = delete;
void someMethods() ...;
private:
std::condition_variable someCondition;
const int someSetup; // warning !!!
int someState {};
}
Должен ли я просто удалить const? Я предполагаю, что первоначальный автор класса хотел убедиться, что это значение действительно не меняется, что выглядит как-то понятно. С другой стороны, если сделать его не-const, это ничего не сломает, пока никто другой не добавит общедоступный сеттер для этого члена.
Почему-то раньше не видел эту ссылку. Спасибо, это действительно полезно!
«Но вы знаете лучший способ [чем использовать const для переменной-члена], чтобы сказать, что закрытый элемент данных не может быть изменен? Нет общедоступного API для его изменения!» Я согласен с этой позицией только потому, что const недостаточно неизменен в языке.





В: Является ли эта проверка слишком строгой, т. е. ведет ли она себя вопреки задокументированному поведению?
О: Да. Цитата из документации:
Эта проверка реализует C.12 из основных рекомендаций C++.
Цитируя название правила C.12:
C.12: Не делайте элементы данных константными или ссылками в копируемом или перемещаемом типе.
(выделено мной).
Тем не менее, он сообщает пример в вопросе, в котором есть член const в некопируемом, неперемещаемом классе.
Разумеется, вся эта информация уже есть в вашем вопросе. Я просто подтверждаю, что ваша интерпретация верна.
Как отмечено в комментариях, документация заканчивается следующим образом:
Дополнительная литература: Элементы данных: никогда не константируйте.
Связанный пост утверждает, что const участники плохие, независимо от того, можно ли скопировать тип. Но согласны вы с этим или нет:
Документация проверки нигде не говорит и не подразумевает, что она реализует другое правило. В нем говорится, что он реализует C.12.
Формулировка «Дальнейшее чтение» звучит так, как будто это ссылка на дополнительный материал, а не что-то, что меняет смысл предшествующей ей документации. Я не удивлен, что это было упущено из виду, прежде чем задать этот вопрос.
Даже если вы щелкнете по нему, в этом сообщении в блоге нет ничего, что указывало бы на то, что оно было написано разработчиком clang-tidy, или что его аргументы оправдывают поведение clang-tidy иначе, чем указано в правиле C.12, не говоря уже о том, что оно отличается от того, что указано в его собственной документации. Похоже, это просто совет разработчикам и не более того.
Следовательно, наличие этой ссылки не меняет вывода о том, что либо проверка работает некорректно, либо ее документация ошибочна.
const?Это довольно субъективно, но я бы сказал, что нет. Квалификатор const кратко передает намерение участника не меняться, и это намерение полезно для читателя.
Связанный пост в блоге утверждает (выделение в оригинале):
Вы можете даже подумать, что это было самодокументируемым: «Этот элемент данных —
const, поэтому он не может измениться». Но знаете ли вы лучший способ сказать, что закрытый член данных не может измениться? Нет общедоступного API для его изменения!
Я категорически не согласен. Гораздо лучше сразу увидеть, что что-то есть const, чем тщательно перебирать весь код, который имеет к нему доступ, и проверять, не меняет ли что-то это. На самом деле, в этом весь смысл const: избавить читателя от этого бремени.
Другое возможное возражение состоит в том, что const не является неизменным. Конечно, это так, но это согласуется с остальной частью дизайна C++, который дает вам полезные ограничения, а также привилегию нарушать их при необходимости. Выбрасывать const, потому что его можно извратить, значит выбрасывать ребенка вместе с водой из ванны. Ни одна языковая особенность не застрахована от неправильного суждения.
В документации по проверке clang-tidy есть ссылка, которая объясняет, почему они решили сделать правило более строгим, чем предполагают основные принципы. Хотя лично я согласен, что это правило слишком строгое.