Prev: Does non- extern const have internal linkage?
Next: I keep running into long term c++ programmers who refuse to use exceptions
From: Johannes Schaub (litb) on 9 Mar 2010 12:25 Andy Venikov wrote: > Alf P. Steinbach wrote: >> * 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. > > I think it's not the whole story. > If you follow this logic, then it'd be impossible to do Curiously > Recurring Template Pattern as sizeof(Derived) isn't known when you > have to instantiate Base<Derived>. > From a core language point of view, a template type argument can be an incomplete type very well (like "void"). So your observation about CRTP doesn't mean anything wrt std::vector. You can't instantiate a standard library "template component" using such an incomplete type. Notice that it makes a difference if you declare struct A { static vector<A> a_; // fine }; vector<A> A::a_; That's fine, because vector<A> is not instantiated at "// fine". > Now it slowly comes back to me. The trick I think is the two-phase > lookup. If you implement vector in such a way that all your > non-dependent manipulations don't need to know the size of the element, > then by the time second phase kicks in, the size of the element is > known. That's why, I think, it all depends on how vector has been > implemented and not strictly on the language rules. > For a class template that's implicitly instantiated, only member declarations but not their definitions are implicitly instantiated. If in their declaration-only part appears no "sizeof(T)" or a concept check for completeness of T or something, it may go unnoticed. So i think i have to correct myself wrt whether the code you show is well- formed or not: It depends on what std::vector does. But it certainly contains undefined behavior. If it takes the sizeof of T, then that would make the program ill-formed (however since the program also contained undefined behavior, no diagnostic is required as said by 1.4/2 last bullet). > BTW, comeau is perfectly happy with the code snipped I gave at the > beginning of this post. > That's just showing it doesn't do sanity checks (with your config, at least). -- [ 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 9 Mar 2010 12:23 * Nick Hounsome: > On 9 Mar, 05:20, "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_; >>> }; >>> 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. > > It is OK because sizeof(A.vec_) is not dependent on sizeof(A) Sorry, no, it's not OK. Your point is relevant for most (all?) in-practice std::vector implementations, but here you're up against formally Undefined Behavior. And that means that in spite of practical considerations some implementation might just not work or compile; it might, to ensure that you're writing Good Code, even check explicitly that type A is complete. > This is just a tarted up way of saying something like: > > struct A > { > struct A* vec_; > }; Sorry, no, that depends on the implementation; see above. Cheers & hth., - Alf -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 9 Mar 2010 22:45 Alf P. Steinbach wrote: > * Nick Hounsome: >> On 9 Mar, 05:20, "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_; >>>> }; >>>> 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. >> >> It is OK because sizeof(A.vec_) is not dependent on sizeof(A) > > Sorry, no, it's not OK. Your point is relevant for most (all?) in-practice > std::vector implementations, but here you're up against formally Undefined > Behavior. And that means that in spite of practical considerations some > implementation might just not work or compile; it might, to ensure that > you're > writing Good Code, even check explicitly that type A is complete. > Do you (or someone else) know if an implementation of std::vector that compiles without errors for an incomplete type could still break at runtime? cheers, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Randy on 10 Mar 2010 04:48 On Mar 9, 8:19 am, Kris Prad <krisp...(a)yahoo.co.uk> wrote: [snip] > 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 > Actually this example appears, IMHO, to be correct based on my reading of the Standard, 9.2, Class Members, paragraph 2, which states that a class is considered as a complete type at several points in the class member specification, explicitly including in ctor initializer lists, as shown above. Randy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Seungbeom Kim on 10 Mar 2010 20:14
Randy wrote: > On Mar 9, 8:19 am, Kris Prad <krisp...(a)yahoo.co.uk> wrote: >> 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 > > Actually this example appears, IMHO, to be correct based on my reading > of the Standard, 9.2, Class Members, paragraph 2, which states that a > class is considered as a complete type at several points in the class > member specification, explicitly including in ctor initializer lists, > as shown above. A::vec_ would be considered as a complete type in the initializer list of A::A(), of course. The issue here is (kind of) the other direction, i.e. whether A would be complete in the instantiation of std::vector<A> which is the type of A::vec_. -- Seungbeom Kim [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |