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