Prev: Does non- extern const have internal linkage?
Next: I keep running into long term c++ programmers who refuse to use exceptions
From: Andy Venikov on 8 Mar 2010 05:04 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 8 Mar 2010 12:27 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 8 Mar 2010 12:20 * 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 8 Mar 2010 20:19 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 9 Mar 2010 00:35
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! ] |