Unrolling loops using templates

A

Ashley

I'm trying to unroll a loop that prints down numbers from the given
number down to 0. I get the following error on Sun C++ 5.5 Patch
113817-12.

-------------------------
"tmp.cpp", line 15: Error: explicit specialization is not allowed in
the current scope.
"tmp.cpp", line 24: Where: While specializing
"printDownContainer<int>".
"tmp.cpp", line 24: Where: Specialized in non-template code.
"tmp.cpp", line 24: Error: Template parameter T requires a type
argument.
-------------------------

How can I correct this? I want to generalize the type of the counter
i. Here's the code.

-------------------------
#include <iostream>

template< typename T >
struct printDownContainer
{
template< T i >
struct printDown {
static void run(void) {
std::cout << i << "\n";
printDown< i - 1 >::run();
}
};

template< >
struct printDown< 0 > {
static void run(void) {
std::cout << 0 << "\n";
}
};
};

int main(void)
{
printDownContainer< int >::printDown< 10 >::run();

return 0;
}
 
V

Victor Bazarov

I'm trying to unroll a loop that prints down numbers from the given
number down to 0. I get the following error on Sun C++ 5.5 Patch
113817-12.

-------------------------
"tmp.cpp", line 15: Error: explicit specialization is not allowed in
the current scope.
"tmp.cpp", line 24: Where: While specializing
"printDownContainer<int>".
"tmp.cpp", line 24: Where: Specialized in non-template code.
"tmp.cpp", line 24: Error: Template parameter T requires a type
argument.
-------------------------

How can I correct this? I want to generalize the type of the counter
i. Here's the code.

-------------------------
#include<iostream>

template< typename T>
struct printDownContainer
{
template< T i>
struct printDown {
static void run(void) {
std::cout<< i<< "\n";
printDown< i - 1>::run();
}
};

template< >
struct printDown< 0> {
static void run(void) {
std::cout<< 0<< "\n";
}
};
};

int main(void)
{
printDownContainer< int>::printDown< 10>::run();

return 0;
}
-------------------------

You can't define/declare a specialization in the class template body.
And you can't specialize a member without specializing the class. What
you could do is to extract your 'printDown' functionality into a
separate template with two arguments and provide a partial
specialization for it:

template<class T, T i> struct printDownHelper {
...
};

template<class T> struct printDownHelper<T,0> {
...
};

And then in your 'printDownContainer' just forward the request to the
helper:

tempate<class T> struct printDownContainer {
tempate<T i> printDown {
static void run() {
printDownHelper<T,i>::doit();
}
}
};

V
 
A

Ashley

I just modified my code to try that, but I get the following error on
the "template<class T> struct printDownHelper<T,0> {" line.

Error: The type of specialized argument i is dependent on another
argument.

Is this because my compiler is old? Here's the new template code.

-------------------------
template< class T, T i >
struct printDownHelper {
static void run(void) {
std::cout << i << "\n";
printDownHelper< T, i - 1 >::run();
}
};

template< class T >
struct printDownHelper< T, 0 > {
static void run(void) {
std::cout << 0 << "\n";
}
};

template< class T >
struct printDownContainer {
template< T i >
struct printDown {
static void run (void) {
printDownHelper< T, i >::run();
}
};
};
 
A

Ashley

Looks like the problem now is that I need to specialize i in
printDownHelper while saying that it's of type T. How can I do that?
Is there a way to annotate the type of 0 in the partial
specialization?
 
M

Marc

Ashley said:
-------------------------
template< class T, T i >
struct printDownHelper {
static void run(void) {
std::cout << i << "\n";
printDownHelper< T, i - 1 >::run();
}
};

template< class T >
struct printDownHelper< T, 0 > {
static void run(void) {
std::cout << 0 << "\n";
}
};
-------------------------

Try this instead:

template< class T, T i, bool b=(i==0) >
struct printDownHelper {
static void run(void) {
std::cout << i << "\n";
printDownHelper< T, i - 1 >::run();
}
};

template< class T, T i >
struct printDownHelper< T, i, true > {
static void run(void) {
std::cout << 0 << "\n";
}
};
 
A

Ashley

Wow, I didn't know you could do that. Thanks, that's what I'm looking
for.
I beginning to like this -- it's getting more & more similar to
Prolog's pattern matching.
 
G

Gil

I'm trying to unroll a loop that prints down numbers from the given
number down to 0.
Thanks in advance.

using namespace boost;

mpl::for_each< mpl::range_c<int,0,10> >(
std::cout << lambda::_1 << " "
);
 

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,999
Messages
2,570,246
Members
46,839
Latest member
MartinaBur

Latest Threads

Top