Scrolling through loops using templates in C ++ with partial specialization

I am trying to use templates to deploy a loop in C ++ as follows.

#include <iostream> template< class T, T i > struct printDown { static void run(void) { std::cout << i << "\n"; printDown< T, i - 1 >::run(); } }; template< class T > struct printDown< T, 0 > { static void run(void) { std::cout << 0 << "\n"; } }; int main(void) { printDown< int, 10 >::run(); return 0; } 

When I compile w / g ++ 3.4.4 in Cygwin, I get the following error.

tmp.cpp: 12: error: type T' of template argument 0' depends on the template parameter

What am I doing wrong? Do I need to somehow annotate 0 to say it is type T?

Thanks in advance.

+6
c ++ templates specialization partial-specialization loop-unrolling
source share
6 answers

Have you tried int i instead of T i ?

+5
source share

Why is this happening? From 14.5.5 / 8,

- the type of the template parameter of the corresponding specialized non-type argument should not depend on the parameter of specialization. [Example:

 template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error 

-end example]

Therefore, when you apply partial specialization, type 0 is T (depends on the parameter of specialization). There are two options: one - to make it independent, for example, change T i to int i, and secondly, apply explicit specialization, and not partial specialization.

Both solutions were issued by others, so I am not going to rewrite them here. At least you know the reason. It is defined by the standard.

+4
source share

As pointed out in phooji , your implementation suffers from a small problem: it quickly generates a long list of calls, which will cause compilers to suffocate quickly.

You can get around this by implementing a slightly more complex version using binary decomposition. I will make it generalized on a functor too, because I'm lazy.

 // Signature template <Functor F, unsigned N> struct UnrolledLoop; 

We need a helper template that saves the parameter offset for passing

 template <Functor F, unsigned N, unsigned OffSet> struct UnrolledImpl; template <Functor F, unsigned OffSet> struct UnrolledImpl<F, 0, OffSet> { static F run(F f) { return f; } }; template <Functor F, unsigned OffSet> struct UnrolledImpl<F, 1, OffSet> { static F run(F f) { f(OffSet); return f; } }; template <Functor F, unsigned N, unsigned OffSet> struct UnrolledImpl { static F run(F f) { F f2 = UnrolledImpl<F, N/2, OffSet>::run(f); return UnrolledImpl<F, N - N/2, OffSet + N/2>::run(f2); } }; 

And you can implement UnrolledLoop simply:

 template <Functor F, unsigned N> struct UnrolledLoop { static F run(F f) { return UnrolledImpl<F, N, 0>::run(f); } } 

Note that you can provide specialization for more N values ​​(3, 4, for example) to be more enjoyable in the compiler.

+1
source share

How to add this to your example:

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

The compiler cannot automatically drop from 0 to int without knowing the type T in advance.

0
source share

Just found it. You can apparently do something like this.

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

I had no idea that this could be done. Very prologish and very nice.

0
source share

You can make a parameter a type parameter for working around

 template< bool > struct bool_ { }; template< class T, T i, typename = bool_<true> > struct printDown { static void run(void) { std::cout << i << "\n"; printDown< T, i - 1 >::run(); } }; template< class T, T i > struct printDown< T, i, bool_<i == 0> > { static void run(void) { std::cout << 0 << "\n"; } }; int main(void) { printDown< int, 10 >::run(); return 0; } 

This way you can specify any conditions that you want in a partial specialization.

0
source share

All Articles