Уже в С++98 у нас были const, volatile, static, extern, inline и, конечно, шаблоны. В С++11 добавились thread_local, constexpr, а также extern для шаблонов. В С++14 добавились шаблоны переменных. В С++17 — inline переменные. В С++20 обещают подвезти consteval и constinit. А вы когда-нибудь задумывались, что такое template static inline thread_local constexpr const volatile переменная?
В этом докладе Михаил попытается разложить по полочкам всё это многообразие ключевых слов. Вспомним про linkage, storage duration и инстанциации шаблонов (и что изменится с приходом модулей в С++20). Разберёмся, какая связь между template и inline, между static и constexpr. Поймём, зачем нам extern, когда у нас есть inline. И осознаем, как нам потребовалось почти 20 лет, чтобы научиться нормально объявлять константы.
Table of Contents:
- Сборка С/С++ программ
- Что такое объявление и определение
- Linkage
- Storage Duration
- Волшебный static
- Const-qualified variables
- Inline переменные
- Constexpr функции
- No diagnostic required
- Комбинации storage duration и linkage
- Алгоритм как определять storage duration
- Extern
- На примерах
- Шаблоны
- Inline functions templates
- Объявление явной инстанции шаблона
- Константы
- C++20
- Рекомендации
Сборка С/С++ программ
Единицы трансляции (translation unit) - сущность формируемая precrocessor, компилируя их мы получаем объектные файлы.

Что такое объявление и определение

Linkage

Второй пример (a’.cpp) не соберется из-за static, т.к. это изменит линковку функции, и она будет видна только в своей единице трансляции.
Всего в C++ есть 3 вида linkage:

External - доступна во всех единицах трансляции.
Internal - только в текущей трансляции.
No - только в текущей области видимости.
Storage Duration

В первом случаем переменная всегда будет 0, во втором же переменная проинициализируется в первый раз 0 и память под нее будет выделена в начале программы, а далее все время будет “жить” и хранить значение.

Волшебный static
Static особенное слово, в зависимости от контекста оно может влиять на линковку, а может на storage duration.

Const-qualified variables

Любая переменная объявленная на уровне пространства имет internal linkage если он cv-qualified. Но в примере ругается линковщик на то, что name это указатель на константные данные, но указатель не const.
Constexpr влечет за собой const:

Пример работы internal linkage:

Inline переменные
Inline работает следующим образом: в каждой единице трансляции на этапе компиляции создается свой объект, но этот символ при попадании в объектник получит отметку weak, и линковщик потом выберет только один.

Constexpr функции

Однако, если функция constexpr qualified то она становится inline .
В современном C++ inline это скорее не про то, что функция будет встраиваться, а про то,что это будет external (weak) linkage и комплятор позаботиться о том, что это функция будет одна.

No diagnostic required
В C++ представленна ситуация ведет к неопределенном поведению и никак не обрабатывается компилятором. И в каждом компиляторе будет свой вывод.
Такие ситуации слишком сложно диагностировать и принято решение не нагружать компиляторы.

Решение данной проблемы заключается в использовании анонимных namespace. Ничего из анонимного пространства имен не торчит наружу. И тогда эти структуры и функции будут иметь internal linkage.

Комбинации storage duration и linkage
Легенда к изображениям:


Алгоритм как определять storage duration


Extern
До появления inline для получения external linkage для переменных использовался extern.
Но у него есть преимущество, если с inline объект помещался бы в каждый объектный файл, то extern приводит к тому, что мы получаем определение переменной, а инициализируется и создается она единожды.


На примерах

Шаблоны
Не бывает шаблонных сущностей, бывают шаблоны сущностей.
При создании шаблонной сущности происходит неявная инстанциация шаблона.

Если вы хотите убедиться, что у вас действительно один объект, используйте inline
(отличный спобос создания констант)

Inline functions templates

Объявление явной инстанции шаблона

Константы

Вот best practice объявления констант:

Но когда введут модули и у нас не будет h файлов, все эти сложности уйдут:

Алгоритм выбора квалификаторов для констант:

C++20




Рекомендации
