473,387 Members | 1,700 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

template recursion depth


Hi,

I want to write a template class that holds another class that uses the
same template. This recursion should stop after a predefined number. I
think it's either impossible or easy, but I have no idea right now :-(

A simplified version is here:

template< unsigned Depth >
class Foo
{
public:
list<int> GetList( const char* word )
{
return foo[*word].GetList( word + sizeof( char ) );
}
private:
Foo< Depth - 1 > foo[27];
};

template<>
class Foo<0>
{
public:
list<int> GetList( const char* word )
{
return _list[*word];
}
private:
list<int> _list[27];
};

The compiler runs through, but I get a stack overflow before main( ) is
reached. It is like a multidimensional lookup table and the number of
dimensions should be determined by a template parameter. The compiler
should be able to inline as much as possible, therefore I don't use
inheritance, virtual functions etc.

I think the point is, how can I prevent the compiler to include Foo<-1>
in Foo<0> ? I bet there is a special trick.

thanks for any help

Ingo
Jul 23 '05 #1
4 2203
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote...
I want to write a template class that holds another class that uses the
same template. This recursion should stop after a predefined number. I
think it's either impossible or easy, but I have no idea right now :-(

A simplified version is here:

template< unsigned Depth >
class Foo
{
public:
list<int> GetList( const char* word )
{
return foo[*word].GetList( word + sizeof( char ) );
'sizeof(char)' is always 1. There is no sense to spell it out. Just
write 1.
}
private:
Foo< Depth - 1 > foo[27];
};

template<>
class Foo<0>
{
public:
list<int> GetList( const char* word )
{
return _list[*word];
}
private:
list<int> _list[27];
};

The compiler runs through, but I get a stack overflow before main( ) is
reached.
How many instantiations are you trying to create? Where is the code
that *uses* your Foo template?

Remember that the size of Foo<N> grows exponentially. The Foo<0> has
27 objects of type 'list<int>'. Even if 'list<int>' is only 4 bytes
long, it's 108 bytes. Foo<1> has 27 Foo<0>'s, that's about 3K. Next
level (Foo<2>) is 78K, next is 2M, next is 55M. Foo<5> is about 1.5G.
Shall I continue or can you do it yourself?
It is like a multidimensional lookup table and the number of dimensions
should be determined by a template parameter. The compiler should be able
to inline as much as possible, therefore I don't use inheritance, virtual
functions etc.

I think the point is, how can I prevent the compiler to include Foo<-1> in
Foo<0> ? I bet there is a special trick.


You already are using that "trick". It's called "specialization".

V
Jul 23 '05 #2

'sizeof(char)' is always 1. There is no sense to spell it out. Just
write 1.


ok, in the real 'not simplified' code it is sizeof( CharT ) and it may
be parameterized to be something else.
I actually expected if I write 1 someone would tell me that it may be a
problem when switching to a different char type.
But you're right, since I spelled it char and not CharT...
}
private:
Foo< Depth - 1 > foo[27];
};

template<>
class Foo<0>
{
public:
list<int> GetList( const char* word )
{
return _list[*word];
}
private:
list<int> _list[27];
};

The compiler runs through, but I get a stack overflow before main( ) is
reached.

How many instantiations are you trying to create? Where is the code
that *uses* your Foo template?

ok, this is important of course

it was:

WordStore<CharUse, 5> store;

and I didn't think 5 is much
Remember that the size of Foo<N> grows exponentially. The Foo<0> has
27 objects of type 'list<int>'. Even if 'list<int>' is only 4 bytes
long, it's 108 bytes. Foo<1> has 27 Foo<0>'s, that's about 3K. Next
level (Foo<2>) is 78K, next is 2M, next is 55M. Foo<5> is about 1.5G.
Shall I continue or can you do it yourself?

but I had to reduce it to Foo<2> to make it >not crash<. I have to admit
that I am a little ashamed not to have tried Foo<2>.
Also I have to admit that I didn't really use int but a
list<WordCounteryCharT> > where WordCounter is holding an unsigned and a
CharT*

How much memory can I expect an empty list to consume? If it is 40
bytes, Foo<3> should use about 20M. Is that too much for a static
memory? Any if it is, should it cause a stack overflow?

It is like a multidimensional lookup table and the number of dimensions
should be determined by a template parameter. The compiler should be able
to inline as much as possible, therefore I don't use inheritance, virtual
functions etc.

I think the point is, how can I prevent the compiler to include Foo<-1> in
Foo<0> ? I bet there is a special trick.

You already are using that "trick". It's called "specialization".

I know I am using specialization. However I didn't expect it to work,
since it seems 'magic' to me and I have not much experience using it
this way.
So, if one could tell me by what rule the compiler did not include the
foo[] for instanciations of Depth = 0, that would take me a good step
forward along the way to understand c++ and meta programming ( it is
meta programming right? )

On the other hand, I would like to have one level more. 20MB is not soo
much memory, I have 1Gb on a WinXP system. Is there a limitation for
static allocetions independant from the hardware and averything else?

And does anybody know, how much memory an empty std::list needs and how
much it uses for any item additionally to the memory for the item
itself? Ok, that may be implementation dependant but any hints are
welcome. I use VC7.1

cheers
Ingo

Jul 23 '05 #3
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote...
[...]
I think the point is, how can I prevent the compiler to include Foo<-1>
in Foo<0> ? I bet there is a special trick.

You already are using that "trick". It's called "specialization".

I know I am using specialization. However I didn't expect it to work,
since it seems 'magic' to me and I have not much experience using it this
way.


No magic. The process of instantiation has to check whether there are
specialisations and if there are, use them instead of generating the
type from the original template.
So, if one could tell me by what rule the compiler did not include the
foo[] for instanciations of Depth = 0, that would take me a good step
forward along the way to understand c++ and meta programming ( it is meta
programming right? )
Since you defined what Foo<Depth == 0> should look like, why should the
compiler "include" anything not in your definition of it?
On the other hand, I would like to have one level more. 20MB is not soo
much memory, I have 1Gb on a WinXP system. Is there a limitation for
static allocetions independant from the hardware and averything else?
If your compiler reports stack overflow during the creation of your
template "chain", it's a limitation of the compiler (the compiler is
just another program with its own memory allocations and algorithms).
You can find more information in a newsgroup dedicated to that compiler.
Try microsoft.public.vc.language.
And does anybody know, how much memory an empty std::list needs
#include <list>
#include <iostream>
int main() {
std::list<int> emptylist;
std::cout << "Empty: " << sizeof emptylist << std::endl;
}
and how much it uses for any item additionally to the memory for the item
itself?
#include <list>
#include <iostream>
int main() {
std::list<int> mylist;
std::cout << "Empty: " << sizeof mylist << std::endl;
mylist.push_back(42);
std::cout << "After one insertion: " << sizeof mylist << std::endl;
}

although I bet you the size of the object doesn't change since all
elements of a list are kept outside of the object itself, and you
will need some other methods to find out how much additional memory
such allocation requires.
Ok, that may be implementation dependant but any hints are welcome. I use
VC7.1


microsoft.public.vc.language

V
Jul 23 '05 #4

Since you defined what Foo<Depth == 0> should look like, why should the
compiler "include" anything not in your definition of it?
Ok, thats clear. I think I got it now. Indeed its not so magic :-)
On the other hand, I would like to have one level more. 20MB is not soo
much memory, I have 1Gb on a WinXP system. Is there a limitation for
static allocetions independant from the hardware and averything else?

If your compiler reports stack overflow during the creation of your
template "chain", it's a limitation of the compiler (the compiler is
just another program with its own memory allocations and algorithms).
You can find more information in a newsgroup dedicated to that compiler.
Try microsoft.public.vc.language.

My compiler never reported anything. This is what I meant by 'compiler
runs through'. It is when I started the program I got stack overflow
before main( ) has been reached. But anyway, you may be right that this
is compiler related.
And does anybody know, how much memory an empty std::list needs

#include <list>
#include <iostream>
int main() {
std::list<int> emptylist;
std::cout << "Empty: " << sizeof emptylist << std::endl;
}


Thank you for that hint. But that is clear. I expected the list to use
additional dynamic memory outside of what I could measure with sizeof.

and how much it uses for any item additionally to the memory for the item
itself?

#include <list>
#include <iostream>
int main() {
std::list<int> mylist;
std::cout << "Empty: " << sizeof mylist << std::endl;
mylist.push_back(42);
std::cout << "After one insertion: " << sizeof mylist << std::endl;
}

although I bet you the size of the object doesn't change since all
elements of a list are kept outside of the object itself, and you
will need some other methods to find out how much additional memory
such allocation requires.

That's what I mean. I think sizeof is always resolved at compile time.

thank you anyway

Ingo

Jul 23 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Georgy Pruss | last post by:
Sometimes I get this error. E.g. >>> sum = lambda n: n<=1 or n+sum(n-1) # just to illustrate the error >>> sum(999) 499500 >>> sum(1000) ............ RuntimeError: maximum recursion depth...
4
by: Dan | last post by:
I've encountered some strange behavior in a recursive procedure I'm writing for a bill of materials. First let me ask directly if what I think is happening is even possible: It seems like the...
2
by: Martin Gernhard | last post by:
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; ...
10
by: MakeMineScotch | last post by:
What's the secret to writing recursive functions that won't crash the computer?
5
by: mast2as | last post by:
Hi guys Here's the class I try to compile (see below). By itself when I have a test.cc file for example that creates an object which is an instance of the class SpectralProfile, it compiles...
13
by: robert | last post by:
My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception. What...
6
by: Andre Kempe | last post by:
hej folks. i have a heap with fixed size and want to determine the depth of a element with given index at compile-time. therefore i wrote some templates. however, when i use template...
2
by: vectorizor | last post by:
Hello all, I am attempting to vectorize few template functions with the Intel compiler, but without much success so far. Ok granted, this question is not 100% c++, but it is related enough that...
6
by: globalrev | last post by:
i received an error maximum recursion depth when processing large amounts of data. i dont know exactly how many recursive calls i made but id assume 50000 or so. is there a definitie limit...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.