Как шаблоны превращают компиляцию в вычисление
Обычная функция выполняет работу, когда запущена программа. Шаблон C++ устроен иначе: он описывает заготовку, из которой компилятор создаёт конкретный код для заданных типов и параметров. Например, шаблон сортировки должен быть приспособлен к тому, какие именно элементы сортируют и как их сравнивают.
На этом этапе компилятор не только подставляет типы. В C++ шаблоны можно использовать для вычислений во время компиляции: результат одного шага становится параметром следующего. Это называют метапрограммированием — программированием, которое строит или вычисляет части другой программы ещё до её запуска.
Почему время растёт незаметно
Сложность возникает, когда шаблоны вложены друг в друга и зависят от множества типов. Чтобы собрать один участок кода, компилятор может последовательно раскрывать цепочку шаблонов, проверять условия и создавать новые специализации — отдельные версии шаблона для конкретных параметров. Если такие цепочки повторяются в разных файлах или библиотеках, работы становится ещё больше.
Особенно затратны большие заголовочные библиотеки: их содержимое обрабатывается при компиляции каждого подключившего их файла. А если после небольшого изменения приходится пересобирать много таких файлов, ожидание складывается из множества повторных вычислений. Поэтому долгий цикл сборки — не обязательно признак медленной программы: значительная часть времени уходит на подготовку кода, который пользователь затем будет выполнять.
Цена гибкости — и способы её снизить
Шаблоны дают возможность писать универсальные и эффективные компоненты: нужный код создаётся под конкретные типы без обязательных затрат на универсальность во время работы. Но часть этой гибкости оплачивается заранее — усилиями компилятора и более сложной диагностикой ошибок, которые могут проходить через длинную цепочку шаблонов.
Обычно проблему ищут в чрезмерных зависимостях между заголовками, слишком сложных шаблонных конструкциях и лишних повторных инстанцированиях. Разделение реализации, сокращение связей и повторное использование уже собранных результатов могут уменьшить объём работы. Часы компиляции возникают не потому, что шаблоны сами по себе медленные, а потому, что компилятору поручили много взаимозависимой работы до запуска программы.






