Все мы при написании кода пользуемся правилами оформления кода. Иногда изобретаются свои правила, в других случаях используются готовые стайлгайды. Однако, любой стайлгайд со временем корректируется и дорабатывается: иногда этому способствуют обновление стандартов языка, иногда меняются тенденции.
В статье приведены изменения Руководства Google по стилю в C++ за 5 лет: с 2019 по 2024.
Краткое содержание изменений:
+ C++20
- NULL
+ концепты 
- #pragma
+ constinit
- std:hash
+ consteval
- u8
+ аргументы-ссылки
- ENUM_VALUE_NAME
+ повесточка и "they" в единственном числе
- здравый смысл


Изменения в «Руководстве» по стилю можно разделить на три направления:

1. Переход на C++20


Основной стандарт языка в Руководстве теперь от 20-го года и отныне код должен соответствовать C++20. Однако, это совсем не означает, что можно использовать новые возможности.
В частности, если планируется портирование кода для различных платформ, то следует оценить целесообразность применения новых возможностей как C++17, так и C++20 и, в некоторых случаях, даже отказаться от них. Но в любом случае создаваемый код должен корректно работать в C++20 (и в качестве примера смотрите про запрет префикса u8 ниже).

Если же C++20 допустим в проекте, то «Руководство» предлагает использовать новые возможности:
— Используйте constinit и consteval
Заметим, что constinit и раньше предлагался к использованию, но только в форме атрибута ABSL_CONST_INIT от внешней кодовой базы. Теперь constinit уже официально внесён в стандарт и рекомендуется к применению.
Что касается consteval, то если вы желаете чтобы функция вычислялась только при компиляции, то лучше применять consteval. А если единственное желание это сделать функцию встраиваемой — то не применять.
— Разрешён оператор трёхстороннего сравнения (оператор «космокорабль», эквивалентности). Его рекомендуется использовать только в тех случаях, когда для двух значений некоторого типа соотношение больше/меньше является очевидным, ясным и единственным. И если всё это выполняется, то рекомендуется определить два оператора: == и <=>. Эти определения должны быть непротиворечивы в части сравнения на равенство. А от остальных операторов сравнения следует избавиться.
С другой стороны, если отношение больше/меньше не такое уж очевидное, или возможно несколько вариантов, то не определяйте оператор <=>.
— Добавилась возможность назначенной инициализации («Designated_initializers»). Назначенная инициализация ранее считалась нестандартным расширением и не рекомендовалась к использованию. После появления в стандарте её можно использовать, но только в виде, совместимом с C++20. Например:
  struct Point {
    float x = 0.0;
    float y = 0.0;
    float z = 0.0;
  };

  Point p = {
    .x = 1.0,
    .y = 2.0,
    // z будет 0.0
  };

Концепты и Ограничения. В «Руководстве» разрешили использовать концепты с ограничениями и сразу сделали дополнительный раздел о том, что такое концепты/ограничения, что можно с ними делать, что нежелательно, какие здесь плюсы и минусы. В целом, всё соответствует логике, но, например, такая форма записи:
template<Concept T>
не рекомендуется.
И вообще, «Руководство» призывает «используйте концепты в разумных количествах, без фанатизма».

2. От чистого C в более безопасный C++


В этой части «Руководство» постаралось перенять хорошие практики, которые ранее были запрещены, и запретить что-то совсем устаревшее.
Ссылочные выходные параметры: одно из явных изменений связано с использованием ссылочных аргументов для выдачи результата (как выходные параметры). Если в ранних версиях «Руководства» ссылки могли использоваться только как входные параметры (в виде константных ссылок), то теперь ссылки используются и для возврата значений в обязательных (т.е. не опциональных) параметрах. Обычные указатели тоже не забыты и всё ещё применяются для возврата значений в опциональных параметрах (для которых допустимо передавать nullptr). И параллельно для опциональных параметров предлагается использовать std::optional — это такая современная альтернатива.
#pragma объявлена недопустимой и не должна использоваться, т.к. это нестандартное расширение. Причём в ранних версиях «Руководства» про неё упоминалось вскользь и только в разделе про программирование под Windows. Теперь это стало общим правилом. С учётом запрета на #pragma once и постепенному переходу к правильно выровненным данным (и сомнительной полезности #pragma pack в этом случае) это может быть логичным решением. Особенно учитывая построение под различные платформы и с применением разных компиляторов.
NULL — конечно же, он тоже теперь под запретом. Если раньше в «Руководстве» ещё были упоминания про C++03 и допускалось использование NULL для совместимости, то теперь есть только nullptr.
раздел std::hash вообще удалён из «Руководства» — видимо, чтобы даже мыслей не было про собственные пользовательские специализации. В целом, наверное это правильное движение, так как создание нормальной хэш-функции для специфических типов может быть совсем нетривиальной задачей.
использование #include-ов ещё больше регламентировано. Во-первых, рекомендуется подключать все используемые заголовочные файлы, не полагаться на вложенные #include-ы (ситуация, когда один заголовочный файл включает другой, тот включает третий и т.д.) и это должно сделать использование заголовочных файлов более самодостаточным и безопасным. Вообще это может быть здравой идеей, но далеко не всегда: например, если вы используете библиотеку, у которой общий заголовочный файл со списком #include-ов (это очень частое решение), то вместо одного общего файла как-бы рекомендуется прописывать весь список — и это ну очень неоднозначное решение.
Также про включение заголовочных файлов есть интересная рекомендация стараться указывать имя файла именно в кавычках (а угловые скобки использовать только по явной необходимости; системные файлы являются такой необходимостью). Такой подход может быть, наверное, полезным, так как пути системных заголовочных файлов всё равно будут использованы в поиске, а возможное упрощение может снизить количество ошибок.

В плане безопасного применения C++ есть тоже подвижки:
enum class: теперь энумераторы объявляются в форме «с областью видимости»:
enum class UrlTableError { ... }
и это может быть полезным в больших кодовых базах.
std::unique_ptr постепенно заменяет обычные указатели, и такой подход тоже может сделать код более безопасным.
Пока эти изменения не указаны как явные рекомендации в тексте, но примеры кода уже обновлены (т.е. существующий код пока можно не переписывать, однако скоро придётся).
constexpr string_view предлагается как предпочтительный тип для глобальных или статических строковых констант. Символьный массив или указатель на первый символ строкового литерала тоже пока ещё допустимы, но направление движения уже в сторону средств C++.
std::bit_cast рекомендуется для приведения типов (ранее рекомендовалось использование absl::bit_cast) и в свете увеличивающегося количества UB это логичное требование.
absl::implicit_cast рекомендуется для приведения типов вверх по иерархии классов. Оно, конечно, и само приводится, но так безопаснее (возможно) и легче ищется по коду (это более вероятно).
переменные thread_local используются всё чаще и в «Руководстве» расширено описание по использованию: расписано как их применять, на что обратить внимание (спойлер: на порядок переменных и их деструкторы: потоки могут создаваться и завершаться часто, деструкторы вызываются постоянно, и для корректной работы всё должно быть в правильном порядке), и инициализировать их в ряде случаев нужно как constinit. В общем, «Руководство» проводит разъяснительную работу и заботится о безопасности кода.
префикс u8 умудрился попасть под запрет: сейчас по возможности избегайте его использования. Префикс u8 стал «нехорошим» после того, как стандартизаторы многое перекроили и теперь в разных стандартах при использовании префикса u8 создаются массивы из символов разного типа: где-то это char[], где-то char8_t[]. Так как есть подозрение, что в следующем стандарте опять могут что-то поменять, то решили, что лучше без префикса.

3. Именование, Комментарии, Пунктуация


В этом направлении «Руководство» тоже обновилось. В целом это ожидаемо, так как основная цель «правильного» написания кода это облегчить его чтение и поддержку.
Именование постепенно уходит от привычек чистого C:
— имена в перечислениях в прописном регистре (ENUM_NAME) теперь применять нельзя. Нужно использовать именование в стиле обычной константы: kEnumName.
— начинается «выдавливание» макросов препроцессора из кода. Пока делаются мягкие воздействия: в макросах препроцессора рекомендуется использовать название проекта, например так:
#define MYPROJECT_ROUND(x)

— добавились правила именования концептов.
Расстановку пробелов и переводов строки переписали и сделали «алгоритм». Раньше это был набор примеров, теперь всё формализовали и ввели понятия: оператор, итерация, лексема, здесь ставим пробел, а здесь перевод строки. В общем намудрили, но, похоже, это вынужденно, так как когда в блоке условия пишется много разного:
} else if (int a = f(); a != 3) {

одними примерами уже не обойтись. К счастью, примеры пока ещё тоже остались: можно по ним изучать пунктуационную мысль.

Также явно обозвали стиль именования «маленькие буквы; слова через подчёркивание»: теперь это называется змеиный стиль.

Повесточка начинает влиять на код. В целом, это было очевидно, что желание не обидеть доберётся и до оформления кода. Вот теперь добралось:
Добавлен раздел про «Инклюзивный Язык», в котором нам объясняют, что использование терминов «белый список» и «чёрный список» не приветствуется, также как и многих других. И вместо местоимений «он» или «она» нужно использовать ангийский «they» или «their» в качестве местоимения единственного числа (видимо, на манер устаревшего местоимения «онЕ»).

Минус Здравый Смысл: к сожалению, был выкинут заключительный раздел, где рекомендовали руководствоваться здравым смыслом и придерживаться постоянства в кодировании. Выкинут целиком. Вот так.


Итог:

Идёт постепенный разворот от чистого C в сторону безопасного и толерантного C++. И «Руководство» есть отражение этого.


Ссылки на версии «Руководства»:
Руководство Google по стилю в C++ 2019: Серия статей на Хабре
Руководство Google по стилю в C++ 2024

Комментарии (5)


  1. Keeper10
    07.09.2024 16:50
    +1

    И вместо местоимений «он» или «она» нужно использовать ангийский «they» или «their» в качестве местоимения единственного числа (видимо, на манер устаревшего местоимения «онЕ»).

    Лучше бы вернули thou/thee в пару к you.


    1. mayorovp
      07.09.2024 16:50

      Чем лучше? Это ж второе лицо, а нужно третье...


      1. Keeper10
        07.09.2024 16:50
        +1

        Тем, что позволяет "тыкать" или "выкать", в зависимости от модальности.

        А третье лицо неопределённого пола уже есть, это it. Почему его до сих пор не применяют к небинарным персонам -- непонятно.


        1. Anton_Menshov
          07.09.2024 16:50
          +1

          Еще Шекспир использовал "they" для единственного числа - тому несложно найти кучу подтверждений (начать с Washington Post и Merriam Webster и продолжить так подробно как хочется самому через гугл). Применение "it" к одушевленным предметам - дерогативно. Поэтому применяем "they" и в некоторых случаях "one" или, если известно более точное местоимение, - то его.


          1. KanuTaH
            07.09.2024 16:50

            Ну а Ломоносов в свое время писал что-нибудь наподобие такого:

            Кто склонность в счастии и доброту являет,
            Тот счастие себе недвижно утверждает.
            Всяк чувствует в тебе и хвалит обое,
            И небо чаемых покажет сбытие.

            Но это же не означает, что и сейчас в быту стоит так же писать.