Когда я в прошлый раз писал о рекурсии, то намеренно не стал писать о рекурсии шаблонной. Во-первых это огромный пласт метапрограммирования, на трюках основано множество интересных вещей, о которых хочется поговорить отдельно, а во-вторых в тех заметках я акцентировался прежде всего на рекурсии времени исполнения (run-time). Шаблоны же, как всем мы знаем – это артифакты времени компиляции.
Оставим, однако, такие расширенные трюки как списки типов в сторону и рассмотрим как могла бы решаться задача с вычислением факториала при помощи шаблонов C++. Алгоритм не меняется даже в случае применения шаблонов:
template
struct Factorial
{
enum { value = N * Factorial::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
Что происходит понять просто если вспомнить рекурсивный алгоритм вычисления факториала. Если аргумент равен нулю, то факториал равен единице. В любом другом случае факториал числа будет равен числу, умноженному на факториал с параметром на единицу меньшем, чем это число.
Т.е. сначала описан шаблон, для общего случая. Для простоты используется перечисление с единственным значением value. При помощи частичной спецификации шаблона выделяется в отдельный случай вычисление факториала для нуля.
Используется эта конструкция следующим образом:
unsigned long int x = Factorial<12>::value;
int y = Factorial<13>::value;
Все плюсы и минусы вычисления факториалов при помощи шаблонов выводятся из того факта, что шаблоны «выполняются» во время компиляции. Компилятор преобразует шаблонную конструкцию в «реальный» код при компиляции. По-этому машинный код может существенно «раздуваться» и содержать, например, полную таблицу вычисленных шаблоном факториалов. А ведь некоторые значения из этого списка даже не используются в программе.
Мне, однако, кажется, что большинство минусов, которые могут быть связаны с шаблонами и методами их применения окупаются возможностью отловить хотя бы часть ошибок при компиляции, а не во время выполнения программы.
Не самый хитрый трюк в области программирования на C++, но надеюсь кому-нибудь он поможет. По крайней мере на примере вычисления факториала можно доказать каким именно способом C++ является мультипарадигменным языком программирования.