Добрый день, Хабралуди! Гуру C++, а также люди, разбирающиеся в метапрограммировании шаблонов, могут смело пропустить эту тему; они не найдут здесь для себя ничего нового.
Однако, если после прочтения заголовка в вашей голове еще не возникло решение данной проблемы (и даже если оно возникло, но не с помощью шаблонов), то милости просим под кат. Собственно решение проблемы:
Давайте разберемся, что к чему.#include <iostream> template<int n> class Factorial { public: static const int f = Factorial<n - 1>::f * n; }; template<> class Factorial<0> { public: static const int f = 1; }; int main() { std::cout << Factorial<5>::f << std::endl; // 120 }
Во-первых, некоторые могут спросить — а почему значение вычисляется на этапе компиляции? Ответ — основа шаблонов в C++.
Специализированный код генерируется на этапе компиляции в зависимости от того, каким типом фактически был параметризован шаблон.
Дело в том, что если вы используете, например, шаблон функции, возвращающий как минимум два значения: template<class T> const T& min(const T& a, const T& b) {
return (a < b) ? a : b;
}
Затем, если вы используете его в программе, например: min(2, 3)
Тогда будет сгенерирована только специализация для типа.
интервал .
А если написать что-то вроде: min(2.0, 3.0)
Затем будет создана специализация для двойной .
Теперь, возвращаясь к нашему факториалу, мы можем понять, что для генерации факториала<5> шаблон, Факториал<4> шаблон должен быть сгенерирован и так далее до нуля, где в факториале записан только один<0> ::f (из-за явной специализации шаблон<> ).
Этот последний шаг останавливает «рекурсивную» генерацию шаблонов, после чего вычисляется само значение факториала.
Почему на этапе компиляции? Потому что константа static const int f является константой времени компиляции.
Если кто-то в это не верит, то можно задать в качестве длины массива какое-нибудь шаблонное значение и наблюдать за спокойной компиляцией программы.
В книге Брюса Оккеля Философия C++.
Практическое программирование .
Дано следующее решение этой задачи (по сути ничем не отличающееся от вышеизложенного): template<int n>
struct {
enum {val = Factorial<n - 1> * n};
};
template<>
struct Factorial<0>{
enum {val = 1};
};
В общем, такой расчет факториала — это частный случай шаблонного метапрограммирования.
Например, возведение целого числа p в степень q можно записать в цикле: int power = 1;
while (q--)
power *= p;
Но это также возможно с использованием метапрограммирования шаблонов: template<int p, int q>
class Power {
public:
static const int value = p * Power<p, q - 1>::value;
};
template<int p>
class Power<p, 0> {
public:
static const int value = 1;
}
Подробнее об этом можно прочитать, например, у Ккеля, в книге Философия C++.
Практическое программирование , или в книге Александреску Современный дизайн на C++ .
Спасибо за внимание! Теги: #C++ #факториал #шаблоны #шаблон #магия шаблонов #C++
-
Ремонт Компьютеров Бангалор
19 Oct, 24 -
Пузырь Роста Рынка Erp-Систем В России.
19 Oct, 24 -
Photoshop Против Fireworks: Сжатие
19 Oct, 24 -
Программа Как Маленькая Жизнь
19 Oct, 24 -
Techcrunch50 – Первые Впечатления
19 Oct, 24 -
Путаница С Агавой
19 Oct, 24 -
Рейтинг Веб-Студий 2008 Г.
19 Oct, 24