From: Nick Hounsome on
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)

This is just a tarted up way of saying something like:

struct A
{
struct A* vec_;
};



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

From: Bo Persson on
Kris Prad 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
>
>

This depends on the standard library compiled against. There is no
requirement that it should compile, but it is allowed.


Bo Persson



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

From: Johannes Schaub (litb) on
Andy Venikov 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.
>

It has undefined behavior, but it's well-formed. ("well-formed" means "a C++
program constructed according to the syntax rules, diagnosable semantic
rules, and the One Definition Rule" - the above program fits all that, i
think).

Since it has undefined behavior, it's not exactly nice code and may still
fail to compile.

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

From: Andy Venikov on
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>.

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.

BTW, comeau is perfectly happy with the code snipped I gave at the
beginning of this post.


Thanks,
Andy.


> Cheers & hth.,
>
> - Alf
>

--
[ 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:
> 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>.

The standard imposes the requirement of complete type for the standard library's
container types' element types.

This is not a requirement for your own container types or general templates.

In particular, that requirement does not say anything about the core language,
and hence nothing whatsoever about the Curiously Recurring Template pattern.


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

Whether it compiles depends on the vector implementation, yes.

If it was not Undefined Behavior then it would not depend on the implementation.


> BTW, comeau is perfectly happy with the code snipped I gave at the
> beginning of this post.

Yes, whether it compiles depends on the implementation.



Cheers & hth.,

- Alf

PS: I skipped adding in discussion of CRT (I actually removed what I'd written
in response to your statements) since, although interesting, it would just be
going off on a tangent, and I thought it best to not mix up the two issues. It's
very easy to get confused when side issues are introduced. So, if you're
interested in CRT then I suggest starting a separate thread.

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