expression template, two arguments, partial specialisation error

M

Martin Gernhard

Hi,

I'm trying to use expression templates to calculate values at compile time.
Doing it with just one parameter is no problem:

///Begin Listing 1
#include <iostream>
using namespace std;

template <int n> void UNROLL(){
cout << "n = " << n << endl;
UNROLL<n-1>();
}

template <> void UNROLL<0>() {
cout << "Hit Zero!" << endl;
}

int main(){
UNROLL<10>();
return 0;
}
///Begin Listing 1

However, if I want to use two parameters, I have to explicitly set both in
the abortion rule like this:

///Begin Listing 2
#include <iostream>

using namespace std;

template <int n, int m> void UNROLL(){
cout << "m*n = " << m*n << endl;
UNROLL<n, m-1>();
}

template <> void UNROLL<5, 0>() {
cout << "Hit Zero!" << endl;
}

int main(){
UNROLL<5, 10>();
return 0;
}
//End Listing 2

Of course, this is not what I want, I want the recursion to abort with
n == (any value) and m == 0. I tried to change the second program like this:

template <int n> void UNROLL<n, 0>() {
cout << "Hit Zero!" << endl;
}

But this gives me the error

temprektest_func.cpp:12: error: partial specialization `UNROLL<n, 0>' of
function template

and more errors about exceeding the maximum instantiation depth of
templates.

I tried google first. I did not find anything exactly like what I wanted,
but guessing from examples involving classes, this seemed to be the syntax
to use. Is this a limitation of my compiler (G++ 3.3.6), am I doing it
wrong or is it simply not possible to specialize expression templates in
this way?

Thanks, Martin
 
V

Victor Bazarov

Martin said:
I'm trying to use expression templates to calculate values at compile time.
[...]
template <int n, int m> void UNROLL(){
cout << "m*n = " << m*n << endl;
UNROLL<n, m-1>();
}

template <> void UNROLL<5, 0>() {
cout << "Hit Zero!" << endl;
}

int main(){
UNROLL<5, 10>();
return 0;
}
//End Listing 2

Of course, this is not what I want, I want the recursion to abort with
n == (any value) and m == 0. I tried to change the second program like this:

template <int n> void UNROLL<n, 0>() {
cout << "Hit Zero!" << endl;
}

But this gives me the error

temprektest_func.cpp:12: error: partial specialization `UNROLL<n, 0>' of
function template

[...]

First of all, there are no partial specialisations of function templates.
Period. Once you admit that to yourself, you can start working towards
a solution, like making your 'UNROLL<n,m>' into a class template.

V
 
M

Martin Gernhard

Victor said:
Martin said:
I'm trying to use expression templates to calculate values at compile
time.
[...]
template <int n, int m> void UNROLL(){
cout << "m*n = " << m*n << endl;
UNROLL<n, m-1>();
}

[...]
template <int n> void UNROLL<n, 0>() {
cout << "Hit Zero!" << endl;
}

But this gives me the error

temprektest_func.cpp:12: error: partial specialization `UNROLL<n, 0>' of
function template

[...]
First of all, there are no partial specialisations of function templates.
Period. Once you admit that to yourself, you can start working towards
a solution, like making your 'UNROLL<n,m>' into a class template.

Thank you very much, this was exactly the clarification I needed. Using the
last example from http://medialab.di.unipi.it/web/AP/MetaProgramming.ppt as
a rough guideline (I found it before my first posting but did not realize I
_needed_ to use classes) the program now calculates binomial coefficients.

To anyone interested, here it is. Because it is ignorant of integer
overflow, its usefulness is probably rather limited.

Thank you very much!

//Listing 1

#include <iostream>

using namespace std;

template <int k> int faculty(){
return k * faculty<k-1>();
}

template<> int faculty<0>(){
return 1;
}

// BinoCoeff - Calculates (n choose k)
template <int n, int k> class BinoCoeff{
public:
static void BinoCoeff::doIt(){
cout << "( " << n << " choose " << k << " ) = "
<< (faculty<n>()/(faculty<k>() * faculty<n-k>())) << endl;
}
};


// BinoCoeffs - Calculates all binomial coefficients
// (n choose k) with k = 0...n.
template <int n, int k, int i> class BinoCoeffs{
public:
static void next(){
BinoCoeff<n, k>::doIt();
BinoCoeffs<n, k+1, i-1>::next();
}
};

template <int n, int k> class BinoCoeffs<n, k, -1>{
public:
static void next(){
}
};


// AllBinoCoeffs - Calculates all binomial coefficients
// of all numbers from n to i.
template <int n, int i> class AllBinoCoeffs{
public:
static void next(){
BinoCoeffs<n, 0, n>::next();
AllBinoCoeffs<n+1, i-1>::next();
}
};

template <int n> class AllBinoCoeffs<n, -1>{
public:
static void next(){
}
};


typedef AllBinoCoeffs<0, 12> BinoCoeffs_0_to_12;

int main(){
BinoCoeffs_0_to_12 *binos = new BinoCoeffs_0_to_12;
binos->next();
delete binos;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,829
Latest member
KimberAlli

Latest Threads

Top