Как компилируются шаблоны
Вопрос
Расскажите, как компилятор обрабатывает шаблоны: когда генерируется код, почему шаблоны в заголовках и чем это грозит проекту.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Шаблон не код, а рецепт; код появляется при инстанцировании
Нужно определение в точке использования: поэтому заголовки
Каждая единица трансляции инстанцирует свои копии, линковщик сливает дубликаты (COMDAT)
Рост времени сборки и размера бинарника
Средства: extern template, явное инстанцирование, модули, предкомпилированные заголовки
Что могут спросить следом
- Нарушает ли ODR одинаковое инстанцирование в разных файлах?
- Как понять, что именно раздувает время сборки?
Разбор
Шаблон сам по себе не порождает машинного кода, это рецепт. Код появляется, когда шаблон используется с конкретными аргументами: компилятор подставляет типы и компилирует получившуюся функцию или класс. Поэтому определение шаблона должно быть видно в каждой единице трансляции, где он инстанцируется, и шаблоны живут в заголовках. В итоге одно и то же std::vector<int>::push_back компилируется во многих .o-файлах, и это законно: такие функции помечены как inline-сущности, а линковщик оставляет одну копию. Платим временем сборки и иногда размером бинарника, если инстанцирований с разными типами очень много. Лечится явным инстанцированием в одном .cpp и extern template в заголовке, вынесением независимой от типа части в нешаблонный код, предкомпилированными заголовками и модулями C++20. Найти виновников помогают -ftime-trace в Clang и анализ размеров символов в бинарнике.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Шаблоны и концепты»
- Дерево отрезков с операцией как параметром шаблона
- Обобщённая функция статистики для чисел и строк
- Один бинарный поиск на все случаи: предикат как параметр шаблона
- Зачем концепты
- Концепты против SFINAE
- Вывод аргументов шаблона класса
- Вывод T при передаче по значению
- Член зависимой базы