Исходя из изложенного, можно сделать следующий вывод:
В системах, где предполагается интенсивное использование обратных вызовов и быстродействие является критически важным, использование универсального аргумента не является оптимальным выбором.
4.7. Проблемы, порождаемые шаблонами
4.7.1. Недостатки шаблонов
Как можно заметить из рассмотренных примеров, шаблоны являются мощным и эффективным инструментом реализации обобщенного кода. Но, как известно, не бывает ничего идеального, поэтому, конечно же, у них имеются недостатки.
Сложность разработки . При проектировании шаблонного кода операции зачастую задаются в декларативном виде, что приближает их к функциональному стилю. Использование пакетов параметров требует изощренных техник, весьма непохожих на классические приемы программирования.
Сложность понимания . Код, написанный с помощью шаблонов, гораздо труднее анализировать, чем обычный. В этом можно убедиться, просмотрев, к примеру, исходный код стандартной библиотеки STL.
Недружественность компилятора. Сообщения об ошибках, генерируемые при компиляции шаблонов, зачастую сложны и непонятны. Когда ошибка показывается где-то в недрах шаблонного кода, очень трудно бывает догадаться, возникает ли проблема из-за некорректной реализации этого кода либо из-за того, что структура данных, подставляемая в шаблон, не реализует предполагаемый интерфейс (например, требуется перегрузка некоторых операторов).
Тщательное тестирование. Шаблоны подчиняются концепции «компиляция по требованию», т. е. компилируются только те функции и методы, которые используются в коде. Поэтому, чтобы убедиться в отсутствии синтаксических и семантических ошибок, следует покрывать вызовами все функции и методы, объявленные в шаблоне. Причем желательно это делать на некотором наборе предполагаемых типов данных.
Большое время компиляции . Во-первых, компилятор осуществляет генерацию кода при каждом инстанциировании шаблона конкретным типом. Во-вторых, шаблоны для одних и тех же типов, инстанциируемые в разных участках программы, будут компилироваться заново. И, в-третьих, много времени тратится на компиляцию включаемых файлов: например, при каждом включении заголовочных файлов стандартной библиотеки все внутренние реализации шаблонов в этих файлах должны быть скомпилированы.
Склонность к разрастанию программного кода. Для каждого используемого типа будет сгенерирован отдельный код. Представим, к примеру, что мы используем шаблонную функцию с входным аргументом – числом, тип которого задается параметром шаблона. Если мы будем вызывать эту функцию с аргументами различных типов, допустим, char, short, int, long, для каждого типа будет сгенерирована отдельная функция, несмотря на то что используемые типы эквивалентны и можно обойтись одним-единственным типом long. Аналогичная ситуация возникает при специализации шаблонов: даже если мы делаем частичную специализацию c целью изменить поведение одного-единственного метода, нам придется повторить весь код, используемый в общей специализации.
4.7.2. Ограничения шаблонов
В общем-то, рассмотренные недостатки не так уж значительны, и преимуществ у шаблонов значительно больше. Тем не менее, они имеют фундаментальное ограничение, вытекающие из их внутренней природы: шаблоны не создают предварительно откомпилированного кода. По большому счету шаблон представляет собой не сам код, а правила для генерации кода. Пока шаблон не инстанциирован, его код отсутствует; после инстанциирования последний генерируется только для тех методов и функций, которые были вызваны. Из указанного ограничения вытекают следующие выводы.
Интерфейс шаблона не может быть отделен от реализации . И объявление шаблона, и его реализация должны находиться в одной области видимости (модель включения). Таким образом, при изменениях в реализации шаблона все компоненты, которые его используют, должны быть перекомпилированы.
Шаблоны не могут поставляться в виде статических или динамических библиотек , они должны поставляться только в виде исходного кода. Никакие сторонние приложения (за исключением компиляторов C++, разумеется) не могут использовать функциональность, реализованную на базе шаблонов.
По вышеуказанным причинам, 29 29 Здесь необходимо уточнить: речь идет только об интерфейсе API, т. е. его видимой части. В реализации API шаблоны использовать можно и нужно.
Читать дальше