Python and generic programming
Diez B. Roggisch
deetsNOSPAM at web.de
Sat Nov 20 08:16:17 EST 2004
> No, you don't quite understand what the OP is asking for. C++
> templates are function or classes that is parameterized by some
> arguments, the parameters can either be integer constants or type
> names. So by writing a single template function you create (or
> actually, you ask the compiler to create on-the-fly) many functions.
> Upon using the parameterized function or class, the compiler will
> choose/create the function or class for you. Specialization is a
> mechanism that allows you to create a function that overrides the
> implementation for some specific parameters. E.g., you can create a
> "factorial" function as a template function:
>
> template <int n>
> int factorial() { return n * factorial<n-1>(); }
>
> so that when asked, the compiler generates factorial<5>() as a
> function which returns 5*factorial<4>(); factorial<4>() as a function
> which returns 4*factorial<3>(), and so on. The terminal condition is
> defined using a specialization:
>
> template <>
> int factorial<0>() { return 1; }
>
> When the compiler wants to generate factorial<0>(), the more
> specialized form is used, which stops the recursion. In this way you
> create a compile-time computed factorial function. During compilation
> the optimizer will turn it into a constant, so no computation is done
> during run-time: factorial<10>() is in every conceivable way an
> integer constant 3628800.
You should mention that C++ lacks the possibility to properly solve
type-equations, so that your provided positive example backfires in cases
where two or more type arguments are needed. An example would be a generic
vector class, that takes the scalar type as argument as well as the
dimension. now for example the multiplying code looks like this:
template <T, N>
void mult(vector<T, N> a, vector<T, N> b) {
a[N] = a[N] * b[N];
mult<T, N-1>(a,b);
}
Now to stop code generation at N=0, you need to write
template <double, 0>
void mult(vector<double, 0> a, vector<double, 0> b) {
a[0] = a[0] * b[0];
}
The above examples are right out of my head, so I can't guarantee they work.
The important thing to observe is that one needs to instantiate the
recursion abortion for the scalar class as well as the dimension 0 - it
won't work like this:
template <T, 0>
void mult(vector<T, 0> a, vector<T, 0> b) {
a[0] = a[0] * b[0];
}
So forgetting to instantiate the used scalar template - for int as example -
will lead to a compiler error, as it tries to generate templates until it
hits the built-in iteration limit.
In functional languages, these things work better, as their pattern-matching
has a notion of "more specialized" patterns over lesser specialized ones.
--
Regards,
Diez B. Roggisch
More information about the Python-list
mailing list