Не компилируйте шаблонный код каждый раз ⌨️
У меня есть травма детства, я не очень люблю шаблоны - считаю, что лучше их использовать в исключительных случаях. Есть не так много случаев, когда классы/методы должны быть шаблонными.
Я использую собственный индикатор: если параметры шаблона в теории заранее неизвестны, то он нужен (например
std::vector<T>).Если все параметры известны (например
void make_sound<TAnimalCat/TAnimalDog/TAnimalBird>()), то лучше сделать виртуальный класс IAnimal.Но часто приходится работать с устоявшейся архитектурой, поэтому представим, что у нас есть шаблоны для конечного числа параметров.
Сам шаблонный код еще ничего не делает. Только когда вызывается метод/класс с некоторыми параметрами шаблона, шаблон "инстанцируется", то есть генерируется уникальный метод/класс под эти параметры.
При компилировании каждого
.cpp-файла (которых может быть сотни) мы часто вынуждены компилировать один и тот же участок кода - пример на godbolt.Инстанцированные шаблонные методы имеют linkage type linkonce_odr, подробнее про него тут - https://t.me/cxx95/38
Чтобы избежать компиляции одного и того же кода в каждом
.cpp-файле, можно под шаблоном "объявить инстанциации" для всех известных параметров через extern template - пример на godbolt.В таком случае где-то нужно "определить инстанциации" - для примера выше нужно в условном
some_header.cpp написать:template int calc<float>();Теперь код в шаблоне будет компилироваться всего один раз.
template int calc<double>();
Однако можно и весь шаблонный код держать в своем
.cpp-файле, часто это упрощает читаемость - пример на godbolt.Можно оценить полезность разных подходов:
🚬 Подход с
extern template является полумерой, потому что обычно выигрыш в скорости компиляции абсолютно незначительный🤤 Подход с шаблонным кодом полностью в своем
.cpp-файле неплох, улучшает читаемость кода