473,466 Members | 1,354 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

recursive type template

I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?

Sep 28 '06 #1
19 2529
n.************@gmail.com wrote:
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully.
Maybe, but the program has undefined behavior: standard templates may only
be instantiated with complete types. It may not show in the implementation
of std::vector in your library, but it might fail in others. The reason
that it is not guaranteed to fail is that the straight forward
implementation of std::vector only uses T* internally. Thus, you have to
put in an extra check to detect incomplete types. Some implementations of
std::vector do that.
What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
Not really. You could do:

#include <utility>

template < typename T >
struct tree : public std::pair< T, tree<T>* {};

int main () {

tree<inta;

}
Best

Kai-Uwe Bux

Sep 28 '06 #2
<n.************@gmail.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
If your 'pair' is really std::pair, and that pair has an instance of each type passed to it as a
member (I assume it does), then you've effectively got struct tree having itself as a member, which
is impossible (since that member has another instance of itself as a member, ad infinitum), and in
its base class to boot, which is even more impossible (???). This problem isn't anything to do with
templates.

Uh, are you sure that 'tree' is a kind of 'pair'?

DW
Sep 28 '06 #3

n.torrey.pi...@gmail.com wrote:
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};
tree<Ttemplate class is not completely defined at the point at which
is being referred as the base class.

Not sure what you are trying to do, but try using CRTP.
Have some of the functionality you need in the base and then pass the
Derived as the templare parameter to the Base, to use it in the
std::pair that you define in the Base.

>
This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
Sep 28 '06 #4

n.************@gmail.com wrote:
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully.

This is because the vector contains the data pointers rather than the
data itself. So you can construct a instance of the tree class in the
memory since you know its size.
>
What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
But here the compiler don't know the size of the class because the tree
in pair<T, tree<T is not define well when it is used to construct
the derived tree. So the compiler give an error.

Try this:

template<typename T>
struct tree : public pair<T, tree<T>* {};

Bests,

Shuisheng

Sep 28 '06 #5
>I have the following tree definition:
>
template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};
maybe this way:

template<typename Tstruct tree
{
T first;
std::vector<tree<T subtrees;
};
int main()
{
tree<pair<int, std::string mytree;

}
Sep 28 '06 #6
Gernot Frisch wrote:
>>I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

maybe this way:

template<typename Tstruct tree
{
T first;
std::vector<tree<T subtrees;
};
That is UB according to [17.4.3.6/2] item 5:

In particular, the effects are undefined in the following cases:
...
? if an incomplete type (3.9) is used as a template argument when
instantiating a template component.
>
int main()
{
tree<pair<int, std::string mytree;

}

Best

Kai-Uwe Bux
Sep 28 '06 #7
That is UB according to [17.4.3.6/2] item 5:

In particular, the effects are undefined in the following cases:
...
? if an incomplete type (3.9) is used as a template argument when
instantiating a template component.
and if I substitute "typename" by "class"?
Sep 28 '06 #8

n.************@gmail.com wrote:
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
template<typename T>
struct tree : public pair<T, tree<T>* {};

make the second part of pair to be a pointer.t

Sep 28 '06 #9
Gernot Frisch wrote:
>
>That is UB according to [17.4.3.6/2] item 5:

In particular, the effects are undefined in the following cases:
...
? if an incomplete type (3.9) is used as a template argument when
instantiating a template component.

and if I substitute "typename" by "class"?
The word "typename" does not occur anywhere in what you quoted. So, what
exactly do you mean?
Best

Kai-Uwe Bux
Sep 28 '06 #10
David W wrote:
<n.************@gmail.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?

If your 'pair' is really std::pair, and that pair has an instance of each type passed to it as a
member (I assume it does), then you've effectively got struct tree having itself as a member, which
is impossible (since that member has another instance of itself as a member, ad infinitum), and in
its base class to boot, which is even more impossible (???). This problem isn't anything to do with
templates.

Uh, are you sure that 'tree' is a kind of 'pair'?
A tree of T is a pair of T and a vector of trees of T. I doesn't have
self as a member - it has a vector of selves as a member.

My pair is like std::pair for the purposes of this discussion, but it
has some useful to me (and the tree) methods defined for it that I
would like to reuse.

Sep 28 '06 #11
It's weird, but both versions compile now (maybe the sysadmin updated
g++, but more likely, I did something different last time)

#include <vector>
#include <utility>

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};

int main() {
tree<intt1; t1.first = 0;
tree<intt2(t1); t1.second.push_back(t2);
}
This compiles with g++ -pedantic -ansi. Those who say that the behavior
is undefined, as far as the standard is concerned, can you point me to
a specific point in the standard that says it?

n.************@gmail.com wrote:
I have the following tree definition:

template<typename T>
struct tree {
T first;
vector<tree<T second; // branches
};

which compiles successfully. What I'd like to do though is to use
another template like 'pair', because I might have a bunch of useful
methods already defined in 'pair':

template<typename T>
struct tree : public pair<T, tree<T {};

This doesn't compile. I tried some forward declarations with no
success. Is there any way to do it?
Sep 28 '06 #12
n.************@gmail.com wrote:
It's weird, but both versions compile now (maybe the sysadmin updated
g++, but more likely, I did something different last time)

#include <vector>
#include <utility>

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};

int main() {
tree<intt1; t1.first = 0;
tree<intt2(t1); t1.second.push_back(t2);
}
This compiles with g++ -pedantic -ansi. Those who say that the behavior
is undefined, as far as the standard is concerned, can you point me to
a specific point in the standard that says it?
Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations on
types used to instantiate standard library template components), the C++
Standard Library depends on components supplied by a C++ program. If
these components do not meet their requirements, the Standard places no
requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.
Best

Kai-Uwe Bux

ps.: please don't top post. It's frowned upon in this group.
Sep 28 '06 #13
>and if I substitute "typename" by "class"?

The word "typename" does not occur anywhere in what you quoted. So,
what
exactly do you mean?
My post was:
template<typename Tstruct tree
....

But, you're perfectly right:

template <class Ttree
{
std::vector<Tsubtrees;
};

does not compile. Sorry for my stupidity. I apologize.
Sep 29 '06 #14

Kai-Uwe Bux wrote:
Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations on
types used to instantiate standard library template components), the C++
Standard Library depends on components supplied by a C++ program. If
these components do not meet their requirements, the Standard places no
requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.
Interesting. This contradicts 14.3.2 's note which says that a template
type argument can be and incomplete type - hence CRTP.

The problem, amongst others is that if Derived derives from Base, its
size is determined by Base. OTOH, if Base depends on derived to such an
extent that its size is determined by derived, then a catch 22 exists.
So it boils down to how std::vector is implemented, which means UB,
yes. A little example:

template <class T>
struct Base
{
int size(){ return sizeof(T); }
//T t_; (1)
};
template <class T>
class Derived : public Base<Derived<T
{
};

int main()
{
Derived<intd;
d.size();
}

....compiles but when I uncomment (1), this does not compile because T
is an incomplete type, and therefore not instantiabable. The code he
submitted compiles under Comeau, but is dependent on whether that STL
vector implementation requires complete types or not.

Regards,

Werner

Sep 29 '06 #15
werasm wrote:
>
Kai-Uwe Bux wrote:
>Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations
on types used to instantiate standard library template components), the
C++ Standard Library depends on components supplied by a C++ program.
If these components do not meet their requirements, the Standard places
no requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.

Interesting. This contradicts 14.3.2 's note which says that a template
type argument can be and incomplete type - hence CRTP.
There is no contradiction: 17.4.3.6 specifies requirements for the use of
components from the standard library. It does not talk about templates in
general.

The problem, amongst others is that if Derived derives from Base, its
size is determined by Base. OTOH, if Base depends on derived to such an
extent that its size is determined by derived, then a catch 22 exists.
So it boils down to how std::vector is implemented, which means UB,
yes. A little example:

template <class T>
struct Base
{
int size(){ return sizeof(T); }
//T t_; (1)
};
template <class T>
class Derived : public Base<Derived<T
{
};

int main()
{
Derived<intd;
d.size();
}

...compiles but when I uncomment (1), this does not compile because T
is an incomplete type, and therefore not instantiabable. The code he
submitted compiles under Comeau, but is dependent on whether that STL
vector implementation requires complete types or not.
Right. And 17.4.3.6 gives license to the implementations of the standard
library (e.g., implementations of std::vector) to use code that requires
template parameters to be complete types.

E.g., the obvious implementation for std::pair<First,Secondwill require
that First and Second are complete types:

template < typename First, typename Second >
struct pair {
First first;
Second second;
...
};

whereas the obvious implementation of std::vector will not. This explains
the observations of the OP.
Best

Kai-Uwe Bux
Sep 29 '06 #16

Kai-Uwe Bux wrote:
There is no contradiction: 17.4.3.6 specifies requirements for the use of
components from the standard library. It does not talk about templates in
general.
Ok, I'll put it this way:

The requirement that the standard library imposes on template arguments
differ from (or oppose) the requirements that are imposed on template
arguments by the standard itself (I call this contradictory - I could
for instance read the standard partially, and believe that my code is
valid). Admittedly, the fact that this is the case is not wrong, but
stems from the fact that the standard don't want to restrict its
implementors (I guess).

No big deal, though - I'm not criticizing the standard. I'm just saying
this could cause ambiguity, and is to an extent (when looking
subjectively, as we so often do), contradictory.

:-),

Werner

Sep 29 '06 #17
werasm wrote:
Kai-Uwe Bux wrote:
>Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations on
types used to instantiate standard library template components), the C++
Standard Library depends on components supplied by a C++ program. If
these components do not meet their requirements, the Standard places no
requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.

Interesting. This contradicts 14.3.2 's note which says that a template
type argument can be and incomplete type - hence CRTP.

The problem, amongst others is that if Derived derives from Base, its
size is determined by Base. OTOH, if Base depends on derived to such an
extent that its size is determined by derived, then a catch 22 exists.
So it boils down to how std::vector is implemented, which means UB,
yes. A little example:

template <class T>
struct Base
{
int size(){ return sizeof(T); }
//T t_; (1)
};
template <class T>
class Derived : public Base<Derived<T
{
};

int main()
{
Derived<intd;
d.size();
}

...compiles but when I uncomment (1), this does not compile because T
is an incomplete type, and therefore not instantiabable. The code he
submitted compiles under Comeau, but is dependent on whether that STL
vector implementation requires complete types or not.

Regards,

Werner
So if you treat STL as an external library, for example if you are using
STLport, you can write it off as an external library dependence, as
opposed to a non-standard use of the language?

For the record, I tested the following in GCC 3.4 (-pedantic -ansi),
Intel 9.1 (-strict-ansi) and MSVC++ (some 0.5 y.o. version). None of
them complained:

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};
Sep 29 '06 #18
n.torrey.pines wrote:
werasm wrote:
>Kai-Uwe Bux wrote:
>>Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations
on types used to instantiate standard library template components),
the C++ Standard Library depends on components supplied by a C++
program. If these components do not meet their requirements, the
Standard places no requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.

Interesting. This contradicts 14.3.2 's note which says that a template
type argument can be and incomplete type - hence CRTP.

The problem, amongst others is that if Derived derives from Base, its
size is determined by Base. OTOH, if Base depends on derived to such an
extent that its size is determined by derived, then a catch 22 exists.
So it boils down to how std::vector is implemented, which means UB,
yes. A little example:

template <class T>
struct Base
{
int size(){ return sizeof(T); }
//T t_; (1)
};
template <class T>
class Derived : public Base<Derived<T
{
};

int main()
{
Derived<intd;
d.size();
}

...compiles but when I uncomment (1), this does not compile because T
is an incomplete type, and therefore not instantiabable. The code he
submitted compiles under Comeau, but is dependent on whether that STL
vector implementation requires complete types or not.

Regards,

Werner

So if you treat STL as an external library, for example if you are using
STLport, you can write it off as an external library dependence, as
opposed to a non-standard use of the language?
I am not sure I understand what you mean. However, this is like many other
issues where the standard says that you get undefined behavior: if you know
what the undefined behavior is that your implementation gets you, then you
are of course perfectly free to make use of that.

For the record, I tested the following in GCC 3.4 (-pedantic -ansi),
Intel 9.1 (-strict-ansi) and MSVC++ (some 0.5 y.o. version). None of
them complained:

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};
In principle, a totally whacky implementation could compile the code but do
surprising things at runtime. As a practical matter, though, this is
nothing to worry about: no library implementor will do that.

As a matter of fact, the natural implementation of std::vector will be
perfectly happy with incomplete types. One would need to put an extra
concept check in on purpose (e.g., to help programmers find UB in their
programs; I would love to have that at least as a debugging tool). This is
easy in this case -- one could just add a typedef:

template < typename T >
class vector {

// stop compilation for incomplete template parameters:
typedef char dummy [sizeof(T)];

...

};

I do not know if any widespread library has that. Your tests indicate the
contrary.

Best

Kai-Uwe Bux
Sep 29 '06 #19
n.torrey.pines wrote:
werasm wrote:
>Kai-Uwe Bux wrote:
>>Sure:

[17.4.3.6/1 and 2]

In certain cases (replacement functions, handler functions, operations
on types used to instantiate standard library template components),
the C++ Standard Library depends on components supplied by a C++
program. If these components do not meet their requirements, the
Standard places no requirements on the implementation.

In particular, the effects are undefined in the following cases:
...
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component.

Interesting. This contradicts 14.3.2 's note which says that a template
type argument can be and incomplete type - hence CRTP.

The problem, amongst others is that if Derived derives from Base, its
size is determined by Base. OTOH, if Base depends on derived to such an
extent that its size is determined by derived, then a catch 22 exists.
So it boils down to how std::vector is implemented, which means UB,
yes. A little example:

template <class T>
struct Base
{
int size(){ return sizeof(T); }
//T t_; (1)
};
template <class T>
class Derived : public Base<Derived<T
{
};

int main()
{
Derived<intd;
d.size();
}

...compiles but when I uncomment (1), this does not compile because T
is an incomplete type, and therefore not instantiabable. The code he
submitted compiles under Comeau, but is dependent on whether that STL
vector implementation requires complete types or not.

Regards,

Werner

So if you treat STL as an external library, for example if you are using
STLport, you can write it off as an external library dependence, as
opposed to a non-standard use of the language?

For the record, I tested the following in GCC 3.4 (-pedantic -ansi),
Intel 9.1 (-strict-ansi) and MSVC++ (some 0.5 y.o. version). None of
them complained:

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};
Just for the record -- the following fails in g++-4.1.1 when concept checks
have been enabled:

#include <utility>
#include <vector>

template<typename T>
struct tree : public std::pair<T, std::vector< tree<T {};

int main ( void ) {
tree< int a;
}
Best

Kai-Uwe Bux
Oct 1 '06 #20

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

Similar topics

2
by: SainTiss | last post by:
Hi, If you've got a template class with lots of methods, and then you've got a type which works with the template, except for one method... What you need to do there is specialize the...
6
by: Johan Bergman | last post by:
Hi, Maybe someone can help me with this one. The following describes a somewhat simplified version of my problem, but I think it will be sufficient. I want to use class factories (virtual...
7
by: Jon Slaughter | last post by:
#pragma once #include <vector> class empty_class { }; template <int _I, int _J, class _element, class _property> class RDES_T {
1
by: Jon Slaughter | last post by:
I've managed to put together a template class that basicaly creates a recursive tree that lets you easily specify the "base" class of that tree and and ending notes and lets you stop the recursive...
4
by: Piotr Filip Mieszkowski | last post by:
Hello, I like both C++ and Lisp and sometimes try to mix their ideas in the code I write. Recently I started to think about writing a pair class similar to the CONS in Lisp. (For those of you...
5
by: Mark Stijnman | last post by:
I am trying to teach myself template metaprogramming and I have been trying to create lists of related types. I am however stuck when I want to make a template that gives me the last type in a...
9
by: Christian E. Böhme | last post by:
Hello all, I ran into a little problem with recursive templates that I am not sure what it has to do with, essentially, since I am currently limited in my access to compilers (namely GCC 4.1)...
3
by: IR | last post by:
Hi, I've been trying to do the following (which doesn't compile) : template<class T, class F = Example<T struct Example { F foo(); };
10
by: AsheeG87 | last post by:
Hello Everyone! I have a linked list and am trying to include a recursive search. However, I am having trouble understanding how I would go about that. I don't quite understand a recursive...
7
by: er | last post by:
hi, could someone please help with this code? template<unsigned int N,unsigned int M> class A{ public: A(); };
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.