 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Carlos Moreno Guest
|
Posted: Mon Sep 05, 2005 11:10 am Post subject: Template M.P. -- why won't this work? |
|
|
I'm struggling with this meta-loop I'm trying to do (basically,
I'm trying to write a "simple" example of a loop unrolled by meta-
programming).
Instead of the typical approach of going down from an int N all
the way to 1 and provide the specialized version for N=1, I want
a loop that goes from N to M (where N and M are arbitrary integer
values -- known at compile-time, of course, and with M > N)
So, I create a wrapper class that uses N and M as non-type params.
But it won't compile. Here's the code (I'm omiting the #include
and the using namespace):
template <int N, int M>
class metaloop
{
template <int X, typename T>
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T>
struct pass<M,T>
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
public:
static void go ()
{
pass
}
};
int main()
{
metaloop<2,10>::go();
return 0;
}
The compiler complains at the point of pass<501,int>. It fails to grab
the specialization pass<M,T>, which in this case would be pass<10,int>,
and instead, it takes the same generic one, which invokes pass<11,int>,
which invokes pass<12,int>.... At 501, the compiler apparently reaches
its recursion limit and reports the error.
Why is that? What am I missing?
Thanks,
Carlos
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gleb Alexeev Guest
|
Posted: Tue Sep 06, 2005 10:48 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
I don't have direct answer to your question but IMHO you seem to
overcomplicate things given your task.
Maybe solution below is what you need?
template <int N, int M>
class metaloop {
public:
static void go () {
std::cout << N << std::endl;
metaloop
}
};
template <int M>
class metaloop<M,M> {
public:
static void go () {
}
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Greg Herlihy Guest
|
Posted: Tue Sep 06, 2005 10:54 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
Carlos Moreno wrote:
| Quote: | I'm struggling with this meta-loop I'm trying to do (basically,
I'm trying to write a "simple" example of a loop unrolled by meta-
programming).
Instead of the typical approach of going down from an int N all
the way to 1 and provide the specialized version for N=1, I want
a loop that goes from N to M (where N and M are arbitrary integer
values -- known at compile-time, of course, and with M > N)
So, I create a wrapper class that uses N and M as non-type params.
But it won't compile. Here's the code (I'm omiting the #include
and the using namespace):
template <int N, int M
class metaloop
{
template
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T
struct pass
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
public:
static void go ()
{
pass
}
};
int main()
{
metaloop<2,10>::go();
return 0;
}
The compiler complains at the point of pass<501,int>. It fails to grab
the specialization pass<M,T>, which in this case would be pass<10,int>,
and instead, it takes the same generic one, which invokes pass<11,int>,
which invokes pass<12,int>.... At 501, the compiler apparently reaches
its recursion limit and reports the error.
Why is that? What am I missing?
Thanks,
Carlos
--
|
It is not possible to specialize a class template nested inside a class
template that is itself not specialized. Furthermore the nested class
template pass is declared private which will make it inaccessible from
the other instantiations of metaloop used in the loop.
When writing template meta-programs, always strive for simplicity
(don't laugh). In this case, the nested template only complicates the
implementation of the recursive go routine. I would suggest using just
one class template to implement the metaloop:
using std::cout;
template <int Counter, int Limit>
class MetaLoop
{
public:
static void Go()
{
cout << Counter << 't' << Counter*Counter << std::endl;
MetaLoop
}
};
template <int Limit>
class MetaLoop<Limit, Limit>
{
public:
static void Go()
{
}
};
int main()
{
MetaLoop<2, 10>::Go();
return 0;
}
Greg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Chang Guest
|
Posted: Tue Sep 06, 2005 10:56 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
Carlos, I made the following changes. This should run OK:
template <int N, int M>
class metaloop
{
public:
template <int X, typename T>
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T>
struct pass<M,T>
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
static void go ()
{
pass
}
};
// here I hard code a explicit template specialization
// to stop the infinite recursion you are experiencing.
// It must use hard-coded integers
template<>
class metaloop<10, 10> {
public:
template <int X, typename T>
struct pass
{
static void go ()
{
cout << "end of recursion" << endl;
}
};
};
Thank you.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Marc Mutz Guest
|
Posted: Tue Sep 06, 2005 11:05 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
Carlos Moreno wrote:
| Quote: | metaloop<N,M>::pass<X+1,T>::go();
|
Not related to your OQ, but for gcc 4.0, I need to write
this as
typedef
typename metaloop<N,M>::template pass<X+1,T> next_pass;
next_pass::go();
Marc
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Tue Sep 06, 2005 11:06 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
Carlos Moreno <moreno_at_mochima_dot_com (AT) xx (DOT) xxx> wrote:
| Quote: | I'm struggling with this meta-loop I'm trying to do (basically,
I'm trying to write a "simple" example of a loop unrolled by meta-
programming).
Instead of the typical approach of going down from an int N all
the way to 1 and provide the specialized version for N=1, I want
a loop that goes from N to M (where N and M are arbitrary integer
values -- known at compile-time, of course, and with M > N)
So, I create a wrapper class that uses N and M as non-type params.
But it won't compile. Here's the code (I'm omiting the #include
and the using namespace):
template <int N, int M
class metaloop
{
template
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T
struct pass
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
public:
static void go ()
{
pass
}
};
int main()
{
metaloop<2,10>::go();
return 0;
}
The compiler complains at the point of pass<501,int>. It fails to grab
the specialization pass<M,T>, which in this case would be pass<10,int>,
and instead, it takes the same generic one, which invokes pass<11,int>,
which invokes pass<12,int>.... At 501, the compiler apparently reaches
its recursion limit and reports the error.
Why is that? What am I missing?
inner classes as template params maybe. but the easiest solution |
is to remove the looping from pass and let it handle the body of the
loop then a specialsation of the looping template is easy. Here is
one solution:
#include <iostream>
template <int X,typename T>
struct pass
{
static void go()
{ // just do one item, looping below.
std::cout << X*X << 'n';
}
};
template
struct do_loop
{
static void go()
{
pass<Start,T>::go();
do_loop<Start+1,Fini,T>::go();
}
};
template <int Start,typename T>
struct do_loop<Start,Start,T>
{
static void go()
{
pass<Start,T>::go();
}
};
int main()
{
do_loop<4,10,int>::go();
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carlos Moreno Guest
|
Posted: Tue Sep 06, 2005 4:14 pm Post subject: Re: Template M.P. -- why won't this work? |
|
|
Greg Herlihy wrote:
| Quote: | It is not possible to specialize a class template nested inside a class
template that is itself not specialized. Furthermore the nested class
template pass is declared private which will make it inaccessible from
the other instantiations of metaloop used in the loop.
|
Oh, d'oh!! This last detail was an oversight -- I was thinking in
terms of the outer class, and saw it as it was that outer class the
one that had to access the other instantiations... (I think the
compiler would have recognized that the class was there and would
have told me that it was private -- if there wasn't the other problem,
that is)
| Quote: | When writing template meta-programs, always strive for simplicity
(don't laugh).
|
Don't worry. I see that the irony is not lost on you :-)
| Quote: | In this case, the nested template only complicates the
implementation of the recursive go routine.
|
The responsibility of the outer class was to create the specialized
version for the upper limit, so that I didn't have to do it explicitly
(that would completely defy the purpose of the exercise I was doing).
| Quote: | template <int Limit
class MetaLoop
|
Neat trick!! I had not seen a way to "automatically" specialize the
upper limit -- the first solution that came to mind was obviously
specializing metaloop<10>, but then what's the point of writing
such thing, if I need to re-write the whole thing each time that
I want to use it? That's why the next solution that I could think
of involved the nested classes, to have one "middle-man" automate
that part for me.
Thanks for the trick!
Carlos
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
graeme prentice Guest
|
Posted: Wed Sep 07, 2005 2:01 pm Post subject: Re: Template M.P. -- why won't this work? |
|
|
On 6 Sep 2005 06:54:25 -0400, Greg Herlihy wrote:
| Quote: |
It is not possible to specialize a class template nested inside a class
template that is itself not specialized.
|
This applies only to explicit specializations. Carlos's code uses a
partial specialization - which is perfectly legal. See 14.5.4.3/2 for
an example.
FWIW - VC7.1 locks up compiling this code, consuming 98% CPU and
increasing memory, requiring task manager to kill it.
Graeme
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Chang Guest
|
Posted: Wed Sep 07, 2005 5:14 pm Post subject: Re: Template M.P. -- why won't this work? |
|
|
Graeme, Using the following template class in MSVC7.1, It compiles it
less than a second , VC7.1 does not lock up and does not requires
increasing memory. Is this the template class you are using? Thank you.
template <int N, int M>
class metaloop
{
public:
template <int X, typename T>
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T>
struct pass<M,T>
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
public:
static void go ()
{
pass
}
};
template<int M>
class metaloop<M, M> {
public:
template <int X, typename T>
struct pass
{
static void go ()
{
cout << "end of recursion" << endl;
}
};
}
int _tmain(int argc, _TCHAR* argv[])
{
metaloop<2, 1000>::go();
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
graeme prentice Guest
|
Posted: Thu Sep 08, 2005 9:16 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
On 7 Sep 2005 13:14:27 -0400, Frank Chang wrote:
| Quote: | Graeme, Using the following template class in MSVC7.1, It compiles it
less than a second , VC7.1 does not lock up and does not requires
increasing memory. Is this the template class you are using? Thank you.
|
No, it locks up using Carlos's code. Your code has syntax errors but if
I correct them, it compiles without locking up. If I change the
following line back to what Carlos had, it locks up.
// no lock up
metaloop<N+1,M>::pass<X+1,T>::go();
// locks up VC7.1
metaloop<N,M>::pass<X+1,T>::go();
Graeme
| Quote: |
template <int N, int M
class metaloop
{
public:
template
struct pass
{
static void go ()
{
cout << X << 't' << X*X << endl;
metaloop
}
};
template <typename T
struct pass
{
static void go ()
{}
// M is excluded (following the usual semi-open
// loops -- as in for (i = N; i < M ... )
};
public:
static void go ()
{
pass
}
};
template<int M
class metaloop
public:
template <int X, typename T
struct pass
{
static void go ()
{
cout << "end of recursion" << endl;
}
};
}
int _tmain(int argc, _TCHAR* argv[])
{
metaloop<2, 1000>::go();
}
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Chang Guest
|
Posted: Thu Sep 08, 2005 2:09 pm Post subject: Re: Template M.P. -- why won't this work? |
|
|
Graeme, I believe you are stating that :
metaloop<N,M>::pass<X+1,T>::go(); locks up VC7.1
This is because of infinite recursion.I experienced the same problem.
But metaloop<N+1,M>::pass<X+1,T>::go();
does not lock , because we advance N -> N + 1 , therefore eventually
N=M and the recursion stops because the compiler sees the explicit
template specialization : template<int M>
class metaloop<M, M>
Please tell me what the compiler errors were and how you fixed
them. Thank you.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Graeme Prentice Guest
|
Posted: Sat Sep 10, 2005 12:34 am Post subject: Re: Template M.P. -- why won't this work? |
|
|
On 8 Sep 2005 10:09:23 -0400, Frank Chang wrote:
| Quote: | Graeme, I believe you are stating that :
metaloop<N,M>::pass<X+1,T>::go(); locks up VC7.1
|
yep, that's what I said, (except for the mysterious minus sign)
| Quote: |
This is because of infinite recursion.I experienced the same problem.
|
No it's not. It's because of a bug in VC7.1. There's no infinite
recursion in Carlos's code as long as N is less than M (and this could
be protected with the help of boost-static-assert). The nested classes
could be a bit expensive memory-wise though, depending on the compiler's
optimisation skills.
| Quote: |
But metaloop<N+1,M>::pass<X+1,T>::go();
does not lock , because we advance N -> N + 1 , therefore eventually
N=M and the recursion stops because the compiler sees the explicit
template specialization : template<int M
class metaloop
Please tell me what the compiler errors were and how you fixed
them. Thank you.
|
IIRC, you lost a semicolon, didn't include
accessed members of namespace std that weren't visible. (Also _tmain
and _TCHAR are non standard).
Graeme
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Chang Guest
|
Posted: Mon Sep 12, 2005 2:52 pm Post subject: Re: Template M.P. -- why won't this work? |
|
|
Graeme, Sorry for the syntax errors from the code posted my email. I
compiled and tested everything and got no VC7.1 errors or warnings and
it ran fine. I admit my cut and paste ignored include files and using
namespace std.
// Carlos code which locks up VC7.1
// metaloop<N,M>::pass<X+1,T>::go();
I agree infinite recursion may be not be the correct semantics.
Maybe I should say infinite loop, As the template instantion
progresses, N never changes and each succesive template instantiation
uses the same N, Therefore N never reaches M and an "infinite loop"
occurs. I checked this out with my VC7.1 debugger. But when I use:
// no lock up if change Carlos code to
// metaloop<N+1,M>::pass<X+1,T>::go();
As the template instantiation progresses , N -> N+1 ->N+2
............->M, so no infinite loop occurs. Thank you.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|