Причина, по которой вы склонны видеть только один способ что-то сделать, состоит в том, что вещи, для которых люди на самом деле используют шаблонное метапрограммирование, обычно являются тривиальными алгоритмически - они просто выглядят сложными, потому что они перепутаны с нагрузкой типа хакерства истранности синтаксиса шаблонов C ++.
Но иногда (как показывает ответ Стива Джессопа) действительно существует несколько алгоритмов для вычисления чего-либо, и вы можете реализовать любой из них с помощью шаблонов.
В качестве другого примераВот два способа оценки pow(a,b)
(для аргументов малого целого):
Очевидное:
// ----- Simple Way -----
template <int A, int B>
struct PowA {
typedef PowA<A,B-1> next;
enum {
value = A * next::value,
recursion_count = 1 + next::recursion_count
};
};
template <int A> struct PowA<A, 1> { enum { value = A, recursion_count = 0 }; };
template <int A> struct PowA<A, 0> { enum { value = 1, recursion_count = 0 }; };
Чуть менее очевидно :
// ----- Less Simple Way -----
template <int A, int B, int IsOdd> struct PowHelper;
template <int A> struct PowHelper<A, 0, 0> { enum { value = 1, recursion_count = 0 }; };
template <int A> struct PowHelper<A, 1, 1> { enum { value = A, recursion_count = 0 }; };
template <int A, int B>
struct PowHelper<A, B, 1> {
typedef PowHelper<A, B-1, 1> next;
enum {
value = A * next::value,
recursion_count = 1 + next::recursion_count
};
};
template <int A, int B>
struct PowHelper<A, B, 0> {
typedef PowHelper<A, B/2, ((B/2)&1)> next;
enum {
x = next::value,
value = x*x,
recursion_count = 1 + next::recursion_count
};
};
template <int A, int B>
struct PowB {
typedef PowHelper<A,B,(B & 1)> helper;
enum {
value = helper::value,
recursion_count = helper::recursion_count
};
};
И некоторый код, чтобы вы могли проверить это:
// ----- Test -----
#include <iostream>
int main(int argc, char* argv[]) {
#define CHECK(X,Y) \
std::cout << ("PowA: " #X "**" #Y " = ") << \
PowA<(X),(Y)>::value << " (recurses " << \
PowA<(X),(Y)>::recursion_count << " times)" << std::endl; \
std::cout << ("PowB: " #X "**" #Y " = ") << \
PowB<(X),(Y)>::value << " (recurses " << \
PowB<(X),(Y)>::recursion_count << " times)" << std::endl;
CHECK(3,3)
CHECK(2,8)
CHECK(7,3)
CHECK(3,18)
#undef CHECK
return 0;
}