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