From: Andy Venikov on
I remember there have been quite a few discussions on this topic
and why

class A
{
vector<A> vec_;
};

is actually well-formed under C++98,
but I can't seem to find any of the threads.

I wanted to revisit all the reasoning behind it.

Could someone refresh my memory as to what it's
well-formed or point to one of those all threads?

Thanks,
Andy.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Pedro Lamarão on
On 8 mar, 19:04, Andy Venikov <swojchelo...(a)gmail.com> wrote:

> I remember there have been quite a few discussions on this topic
> and why
>
> class A
> {
> vector<A> vec_;
>
> };
>
> is actually well-formed under C++98,
> but I can't seem to find any of the threads.

GCC accepts it:

[pedro.lamarao(a)elisa Projetos]$ cat test.cpp
#include <vector>

struct A
{
std::vector<A> vec_;
};

[pedro.lamarao(a)elisa Projetos]$ g++ -c test.cpp
[pedro.lamarao(a)elisa Projetos]$

IIRC, the template argument to std::vector is allowed to be an
incomplete type.

--
P.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alf P. Steinbach on
* Andy Venikov:
> I remember there have been quite a few discussions on this topic
> and why
>
> class A
> {
> vector<A> vec_;
> };
>
> is actually well-formed under C++98,

Assuming that 'vector' is 'std::vector' it's not well-formed (see below).


> but I can't seem to find any of the threads.
>
> I wanted to revisit all the reasoning behind it.
>
> Could someone refresh my memory as to what it's
> well-formed or point to one of those all threads?

A type T is "incomplete" at a point where you can't do sizeof(T), otherwise it's
complete; the element type of a standard library container must be complete.

So, for a standard library container type C, if you can do sizeof(E) where E is
the container element type, then at this point you use C<E>, otherwise not.


Cheers & hth.,

- Alf

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Kris Prad on
On Mar 9, 5:20 am, "Alf P. Steinbach" <al...(a)start.no> wrote:
> * Andy Venikov:
>
> > I remember there have been quite a few discussions on this topic
> > and why
>
> > class A
> > {
> > vector<A> vec_;
> > };
>

> So, for a standard library container type C, if you can do sizeof(E) where E is
> the container element type, then at this point you use C<E>, otherwise not.
>
> Cheers & hth.,
>
> - Alf
>

Comeau accepts even this:

#include <vector>


struct A
{
std::vector<A> vec_;
A(): vec_(10) {} // <----- with size
};

BUT NOT THIS:

struct B;
std::vector<B> vec2_; // incomplete type error



Kris


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 9 Mrz., 14:19, Kris Prad <krisp...(a)yahoo.co.uk> wrote:
> On Mar 9, 5:20 am, "Alf P. Steinbach" <al...(a)start.no> wrote:
> > * Andy Venikov:
>
> > > I remember there have been quite a few discussions on this topic
> > > and why
>
> > > class A
> > > {
> > > vector<A> vec_;
> > > };
>
> > So, for a standard library container type C, if you can do sizeof(E) where E is
> > the container element type, then at this point you use C<E>, otherwise not.
>
> > Cheers & hth.,
>
> > - Alf
>
> Comeau accepts even this:
>
> #include <vector>
>
> struct A
> {
> std::vector<A> vec_;
> A(): vec_(10) {} // <----- with size
> };
>
> BUT NOT THIS:
>
> struct B;
> std::vector<B> vec2_; // incomplete type error

It doesn't matter, what Comeau accepts, the C++
standard (both C++03 and C++0x) says that what
you are trying causes undefined behaviour, see
[lib.res.on.functions]/2:

"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."

In your example std::vector<A> will be instantiated,
because vec_ is a non-static data member of A.

The standard does not distinguish here between
instantiation of the class template declaration and
individual member instantiation of that template.
Usually, it "works", but the standard does not
provide fine-grained instantiation guarantees and
in this particular implementation the definition
of the std::vector class does not require T to be
complete. Within the body of any member function
the class is considered as complete anyway,
therefore usage of A will probably be well-defined
for *this particular* implementation.

B is not even complete within the body of the
constructor of vector<B>.

A conforming compiler could quite easily break
either case by adding a static_assert in the
class definition like this:

template<typename T, ...>
class vector {
typedef char __test_complete[sizeof(T)];
...
};

Some (most?) implementations usually don't do
this because user's would like to take advantage
of incomplete types in several scenarios, but this
belongs all to the domain of quality of
implementation.

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]