Topic: Compiler differences: which is correct?


Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: Mon, 10 Dec 2001 00:50:35 GMT
Raw View
Michiel Salters<Michiel.Salters@cmg.nl> writes:

> 9.2/8 [ class members ] "
> 8 Non-static (9.4) members that are class objects shall be objects of previously
> defined classes. " - although it also suffers a bit from
> the "object" part.

I see; thanks for pointing it out.

> Does this warrant a DR? I certainly think this is surprising.
> Explicitly outlawing it would break some arguably legal constructs, but
> they probably didn't compile anyhow. So it wouldn't break any programs.

Since people in this group have read the standard differently
(including people who are very experienced in this on both sides), it
definitely sounds like an ambiguity to me, which should be reported.

It may be that the committee finds that there is no defect, then we
will know for sure also.

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: jthill_@mac.com (Jim Hill)
Date: Mon, 10 Dec 2001 16:46:52 GMT
Raw View
pdimov@mmltd.net (Peter Dimov) wrote in message news:<7dc3b1ea.0112060906.4f610e14@posting.google.com>...
> "James Kuyper Jr." <kuyper@wizard.net> wrote in message news:<3C0C2E6E.ED96EC18@wizard.net>...
> > Martin von Loewis wrote:
> > > I would argue that this doesn't apply: myvar is not an object, it is a
> > > template member. ...
> > It's a template member with an object type. That type is an incomplete
> > one, hence the problem.

> I disagree. There is no object named 'myvar' in the above program. The
> closest is B<int>::myvar, but EDG 2.45 gives an error before
> encountering B<int>.

I agree so far,

> The justification for the error is, I believe, 14.6/7: "If no valid
> specialization can be generated from a template definition, and that
> template is not instantiated, the template definition is ill-formed,
> no diagnostic required."

but not with this.

14.6p6/7 prohibit misleading the compiler about whether a name is
going to resolve to a typename or not and point out that when or
whether template definitions that can never be properly instantiated
are diagnosed is a QoI issue, but "no valid specialization can be
generated" doesn't say, and doesn't mean, "at the point of
definition".

Look at the examples: it's unspecified whether `void g(T t,int a,char*
b) { a=b; }` or even `void g(T t) { + }` _may_ be diagnosed in
uninstantiated templates, but `void h(T &t, int i) { t=i; }` is
diagnosed only if "instantiatedand the assignment to t is an error".

As-yet-uninstantiated templates don't require complete definitions,
only declarations:

14.6p9:
| If a name does not depend on a template parameter (as defined in
| 14.6.2), a declaration (or set of declarations) for that name shall
| be in scope at the point where the name appears in the template
| definition; the name is bound to the declaration (or declarations)
| found at that point and this binding is not affected by declarations
| that are visible at the point of instantiation.

3.9p7:
| A class type (such as "class X") might be incomplete at one point
| in a translation unit and complete later on; the type "class X" is
| the same type at both points.

> This means that EDG 2.45 "thinks" that, as soon as B<X> is
> instantiated (with any X,) B<X>::myvar would violate 3.1/6, since A is
> bound at definition time, and refers to an incomplete type.

Whether this is EDG's reasoning or not, I think EDG's wrong.  Class
template definitions are not type declarations, they're template
definitions. `A` is bound to a type at the definition point, and that
type is complete at the instantiation point, where, for the first time
in the given code, a type [`class B<int>`] is defined that uses it.

Jim

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Tue, 11 Dec 2001 16:50:14 GMT
Raw View
"Jim Hill" <jthill_@mac.com> wrote in message
news:a8af2f56.0112091625.b9637c5@posting.google.com...
> pdimov@mmltd.net (Peter Dimov) wrote in message
news:<7dc3b1ea.0112060906.4f610e14@posting.google.com>...
> > "James Kuyper Jr." <kuyper@wizard.net> wrote in message
news:<3C0C2E6E.ED96EC18@wizard.net>...
> > > Martin von Loewis wrote:
> > > > I would argue that this doesn't apply: myvar is not an object, it is
a
> > > > template member. ...
> > > It's a template member with an object type. That type is an incomplete
> > > one, hence the problem.
>
> > I disagree. There is no object named 'myvar' in the above program. The
> > closest is B<int>::myvar, but EDG 2.45 gives an error before
> > encountering B<int>.
>
> I agree so far,
>
> > The justification for the error is, I believe, 14.6/7: "If no valid
> > specialization can be generated from a template definition, and that
> > template is not instantiated, the template definition is ill-formed,
> > no diagnostic required."
>
> but not with this.
>
> 14.6p6/7 prohibit misleading the compiler about whether a name is
> going to resolve to a typename or not and point out that when or
> whether template definitions that can never be properly instantiated
> are diagnosed is a QoI issue, but "no valid specialization can be
> generated" doesn't say, and doesn't mean, "at the point of
> definition".
>
> Look at the examples: it's unspecified whether `void g(T t,int a,char*
> b) { a=b; }` or even `void g(T t) { + }` _may_ be diagnosed in
> uninstantiated templates, but `void h(T &t, int i) { t=i; }` is
> diagnosed only if "instantiatedand the assignment to t is an error".
>
> As-yet-uninstantiated templates don't require complete definitions,
> only declarations:
>
> 14.6p9:
> | If a name does not depend on a template parameter (as defined in
> | 14.6.2), a declaration (or set of declarations) for that name shall
> | be in scope at the point where the name appears in the template
> | definition; the name is bound to the declaration (or declarations)
> | found at that point and this binding is not affected by declarations
> | that are visible at the point of instantiation.
>
> 3.9p7:
> | A class type (such as "class X") might be incomplete at one point
> | in a translation unit and complete later on; the type "class X" is
> | the same type at both points.
>
> > This means that EDG 2.45 "thinks" that, as soon as B<X> is
> > instantiated (with any X,) B<X>::myvar would violate 3.1/6, since A is
> > bound at definition time, and refers to an incomplete type.
>
> Whether this is EDG's reasoning or not, I think EDG's wrong.  Class
> template definitions are not type declarations, they're template
> definitions. `A` is bound to a type at the definition point, and that
> type is complete at the instantiation point, where, for the first time
> in the given code, a type [`class B<int>`] is defined that uses it.

When defining the template, the compiler is allowed (but not required) to
issue a diagnostic if the template cannot be instantiated (from 14.6p7). If
"A" has a private constructor or destructor, then the template B cannot be
instantiated due to access rules. Similarly, if A contains a member of type
B<X> for some X. However, if "A" is incomplete, then the compiler cannot
know this at the point of definition, which IMO makes the code ill-formed,
since the compiler cannot determine whether or not the diagnostic it is
permitted to issue applies or not. This does not mean that all compilers
will complain, only that they are allowed to. This follows the same
reasoning as diagnostics on violations of the ODR --- not all
implementations can or will diagnose all violations of the ODR, but that
doesn't make the code that violates it any more valid.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: Thu, 6 Dec 2001 18:36:17 GMT
Raw View
Michiel Salters<Michiel.Salters@cmg.nl> writes:

> And what would be the offending object? "Object" is a very specific term
> in C++.

I can follow your reasoning that it is only ill-formed to create
objects of incomplete type, so 3.1 would not apply to a template
member. Assuming that interpretation, what part of the standard rules
out the translation unit

struct X;
struct Y{
  X x;
};

Here, the same reasoning could apply: This is only ill-formed if you
create instances of Y. However, it appears to be common understanding
that this is ill-formed on its own right.

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 6 Dec 2001 18:42:31 GMT
Raw View
"James Kuyper Jr." <kuyper@wizard.net> wrote in message news:<3C0C2E6E.ED96EC18@wizard.net>...
> Martin von Loewis wrote:
> >
> > Adam Peterson <ahp6@email.byu.edu> writes:
> >
> > > > class A;  // forward declaration
> > > >
> > > > template <class X> class B {
> > > > { A myvar;
> > > > ...
> > > > };
> > > >
> > > > class A {
> > > > ...
> > > > }
> > > >
> > > > ... B<int> ...
> > >
> > > The above is ill-formed, as a consequence of the definition of 'myvar'.
> > > Section 3.1 paragraph 6:
> > > A program is ill-formed if the definition of any object gives the object an
> > > incomplete type (3.9).
> >
> > I would argue that this doesn't apply: myvar is not an object, it is a
> > template member. ...
>
> It's a template member with an object type. That type is an incomplete
> one, hence the problem.

I disagree. There is no object named 'myvar' in the above program. The
closest is B<int>::myvar, but EDG 2.45 gives an error before
encountering B<int>.

The justification for the error is, I believe, 14.6/7: "If no valid
specialization can be generated from a template definition, and that
template is not instantiated, the template definition is ill-formed,
no diagnostic required."

This means that EDG 2.45 "thinks" that, as soon as B<X> is
instantiated (with any X,) B<X>::myvar would violate 3.1/6, since A is
bound at definition time, and refers to an incomplete type.

My first thought was that this is a defect, but actually it's not.
Even without this restriction, B<> cannot be used without defining A
first, so moving the definition of A before the definition of B<> does
not create a dependency. If, on the other hand, the definition of A is
supposed to be provided by the user, A can be made a template
parameter of B.

--
Peter Dimov
Multi Media Ltd.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Fri, 7 Dec 2001 17:30:52 GMT
Raw View
In article <j4d71szjcz.fsf@informatik.hu-berlin.de>, Martin von Loewis says...
>
>Michiel Salters<Michiel.Salters@cmg.nl> writes:
>
>> And what would be the offending object? "Object" is a very specific term
>> in C++.
>
>I can follow your reasoning that it is only ill-formed to create
>objects of incomplete type, so 3.1 would not apply to a template
>member. Assuming that interpretation, what part of the standard rules
>out the translation unit
>
>struct X;
>struct Y{
>  X x;
>};

9.2/8 [ class members ] "
8 Non-static (9.4) members that are class objects shall be objects of previously
defined classes. " - although it also suffers a bit from
the "object" part.

Does this warrant a DR? I certainly think this is surprising.
Explicitly outlawing it would break some arguably legal constructs, but
they probably didn't compile anyhow. So it wouldn't break any programs.

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "David Crocker" <dcrocker@imsltd.com>
Date: Tue, 4 Dec 2001 19:39:16 GMT
Raw View
Thanks to everyone who responded. The consensus seems to be that if A is an
incomplete type, it is fine to static_cast zero to A*, but it is not OK to
declare a class template to have a member of type A even if A is complete at
the earliest point of instantiation of the template.

One bug report is on its way to Borland and one fix to our own code is
underway.
--
David Crocker, Escher Technologies Ltd. www.eschertech.com


"David Crocker" <dcrocker@imsltd.com> wrote in message
news:3c07c8fb$0$8507$ed9e5944@reading.news.pipex.net...
> In trying to generate portable C++ code from a specification, we have come
> across some code fragments to do with incomplete types that are accepted
by
> some compilers and not others. Can anyone conform the correct behaviour
and
> point me to the relevant clauses in the standard?
>
> First fragment:
>
> class A;   // forward declaration
> ...
> ... static_cast<A*>(0) ...  // null pointer of type A*
> ...
> class A{  // declaration of class A
> ...
> }
>
> Some compilers accept the static cast of 0 to A* where A is an incomplete
> type; others (e.g. Borland bcc55) do not. All accept a C-style cast, i.e.
> (A*)(0) instead.
>
> Second construct:
>
> class A;  // forward declaration
>
> template <class X> class B {
> { A myvar;
> ...
> };
>
> class A {
> ...
> }
>
> ... B<int> ...
>
> Here, some compilers (e.g. Intel Linux compiler, Comeau) refuse to accept
> the template declaration because A is an incomplete type at that point;
> others (e.g. Intel Windows compiler, VC++ 6, Borland) are happy, provided
> class A has been defined before the template is instantiated. Which is
> correct?
>
> --
> David Crocker, Escher Technologies Ltd. www.eschertech.com
>
>
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
>


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: gottlobfrege@hotmail.com (Gottlob Frege)
Date: Wed, 5 Dec 2001 16:51:31 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message news:<9ufhdf$872k5$1@ID-49767.news.dfncis.de>...
> "David Crocker" <dcrocker@imsltd.com> wrote in message
> news:3c07c8fb$0$8507$ed9e5944@reading.news.pipex.net...
> > In trying to generate portable C++ code from a specification, we have come
> > across some code fragments to do with incomplete types that are accepted
>  by
> > some compilers and not others. Can anyone conform the correct behaviour
>  and
> > point me to the relevant clauses in the standard?
> >
> > First fragment:
> >
> > class A;   // forward declaration
> > ...
> > ... static_cast<A*>(0) ...  // null pointer of type A*
>
> Pointers to incomplete types are themselves complete, so this is fine.
>
> 3.9.2p3:
> "... Pointers to incomplete types are allowed although there are
> restrictions on what can be done with them ..."
>
> > Second construct:
> >
> > class A;  // forward declaration
> >
> > template <class X> class B {
> > { A myvar;
> > ...
> > };
>
> A is a non-dependent name, so is resolved at the point of definition of the
> template.
>
> 14.6.3p1:
> "Non-dependent names used in a template definition are found using the usual
> name lookup and bound at the point they are used."
>

the point they are USED. Has A been used yet?  Does the standard give
a good definition for "used" in this context.  I would naively
translate "used" to be instantiated, meaning the code should be
fine.... but what do I know?


> This template definition defines the member myvar to be of type A. This is
> ill-formed, since A is an incomplete type at this point.
>
> 3.1p6:
> "A program is ill-formed if the definition of any object gives the object an
> incomplete type"
>
> Anthony
> --
> Anthony Williams
> Software Engineer, Nortel Networks Optical Components Ltd
> The opinions expressed in this message are not necessarily those of my
> employer
>
>
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: Mon, 3 Dec 2001 18:36:50 GMT
Raw View
Adam Peterson <ahp6@email.byu.edu> writes:

> > class A;  // forward declaration
> >
> > template <class X> class B {
> > { A myvar;
> > ...
> > };
> >
> > class A {
> > ...
> > }
> >
> > ... B<int> ...
>
> The above is ill-formed, as a consequence of the definition of 'myvar'.
> Section 3.1 paragraph 6:
> A program is ill-formed if the definition of any object gives the object an
> incomplete type (3.9).

I would argue that this doesn't apply: myvar is not an object, it is a
template member. If you were supposed to check template members at
template declaration time, how could you find out whether

template<class X> class B{
  X myvar;
};

is well-formed or not?

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Mon, 3 Dec 2001 18:42:43 GMT
Raw View
In article <3c07c8fb$0$8507$ed9e5944@reading.news.pipex.net>, David Crocker
says...
>
>In trying to generate portable C++ code from a specification, we have come
>across some code fragments to do with incomplete types that are accepted by
>some compilers and not others. Can anyone conform the correct behaviour and
>point me to the relevant clauses in the standard?
>
>First fragment:
[ Easy, see other posts]

>Second construct:
>
>class A;  // forward declaration
>
>template <class X> class B {
>{ A myvar;
>...
>};
>
>class A {
>...
>}
>
>... B<int> ...
>
>Here, some compilers (e.g. Intel Linux compiler, Comeau) refuse to accept
>the template declaration because A is an incomplete type at that point;
>others (e.g. Intel Windows compiler, VC++ 6, Borland) are happy, provided
>class A has been defined before the template is instantiated. Which is
>correct?

Difficult. The standard may be a bit unclear (and you, too).
It has been correctly noted that the name A is looked up as a non-dependant
name in B, so as the point of binding A has an incomplete type.
However, the subsequent quoting of 3.1 seems wrong to me. A class
member isn't an object (see 1.8) Clearly you can't create objects
of type B<int> because of 3.1. An object member is an object in its
own right. So creating an B<int> object would create a (sub)object
of incomplete type, which would violate 3.1. However, the type B<int>*
would be complete. So how is B<int> used ?

No, this is not useful. Nothing that you do to B<int> will make A
complete, except moving its definition. So you can have B<int>*, but all
it can ever point to is 0.

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Mon, 3 Dec 2001 18:42:28 GMT
Raw View
In article <9ucq94$per$1@acs2.byu.edu>, Adam Peterson says...
>
>
>"David Crocker" <dcrocker@imsltd.com> wrote in message
>> class A;  // forward declaration
>>
>> template <class X> class B {
>> { A myvar;
>> ...
>> };
>>
>> class A {
>> ...
>> }
>>
>> ... B<int> ...
>
>The above is ill-formed, as a consequence of the definition of 'myvar'.
>Section 3.1 paragraph 6:
>A program is ill-formed if the definition of any object gives the object an
>incomplete type (3.9).

And what would be the offending object? "Object" is a very specific term
in C++.

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Tue, 4 Dec 2001 19:35:02 GMT
Raw View
Martin von Loewis wrote:
>
> Adam Peterson <ahp6@email.byu.edu> writes:
>
> > > class A;  // forward declaration
> > >
> > > template <class X> class B {
> > > { A myvar;
> > > ...
> > > };
> > >
> > > class A {
> > > ...
> > > }
> > >
> > > ... B<int> ...
> >
> > The above is ill-formed, as a consequence of the definition of 'myvar'.
> > Section 3.1 paragraph 6:
> > A program is ill-formed if the definition of any object gives the object an
> > incomplete type (3.9).
>
> I would argue that this doesn't apply: myvar is not an object, it is a
> template member. ...

It's a template member with an object type. That type is an incomplete
one, hence the problem.

> ...If you were supposed to check template members at
> template declaration time, how could you find out whether
>
> template<class X> class B{
>   X myvar;
> };
>
> is well-formed or not?

The standard distinguishes between dependent names and non-dependent
names. X is non-dependent in class A, but is a dependent name in Class
B.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "David Crocker" <dcrocker@imsltd.com>
Date: Fri, 30 Nov 2001 12:04:16 CST
Raw View
In trying to generate portable C++ code from a specification, we have come
across some code fragments to do with incomplete types that are accepted by
some compilers and not others. Can anyone conform the correct behaviour and
point me to the relevant clauses in the standard?

First fragment:

class A;   // forward declaration
...
... static_cast<A*>(0) ...  // null pointer of type A*
...
class A{  // declaration of class A
...
}

Some compilers accept the static cast of 0 to A* where A is an incomplete
type; others (e.g. Borland bcc55) do not. All accept a C-style cast, i.e.
(A*)(0) instead.

Second construct:

class A;  // forward declaration

template <class X> class B {
{ A myvar;
...
};

class A {
...
}

... B<int> ...

Here, some compilers (e.g. Intel Linux compiler, Comeau) refuse to accept
the template declaration because A is an incomplete type at that point;
others (e.g. Intel Windows compiler, VC++ 6, Borland) are happy, provided
class A has been defined before the template is instantiated. Which is
correct?

--
David Crocker, Escher Technologies Ltd. www.eschertech.com



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: Mon, 3 Dec 2001 00:03:50 GMT
Raw View
"David Crocker" <dcrocker@imsltd.com> writes:

> class A;   // forward declaration
> ...
> ... static_cast<A*>(0) ...  // null pointer of type A*
> ...
> class A{  // declaration of class A
> ...
> }
>
> Some compilers accept the static cast of 0 to A* where A is an incomplete
> type; others (e.g. Borland bcc55) do not. All accept a C-style cast, i.e.
> (A*)(0) instead.

According to 5.2.9/2, this cast is correct if

A *pa(0);

would be correct. According to 3.9.2/3, pointers to incomplete types
are allowed. 3.9/6 rules out creating objects of incomplete type, but
since A* is a complete type, this rule does not apply. According to
4.10/1, a null pointer constant (such as the literal 0) can be
converted to a pointer type, giving the null pointer value of this
type. There are no further restrictions on this conversion, so this
cast is well-formed.



> class A;  // forward declaration
>
> template <class X> class B {
> { A myvar;
> ...
> };
>
> class A {
> ...
> }
>
> ... B<int> ...
>
> Here, some compilers (e.g. Intel Linux compiler, Comeau) refuse to accept
> the template declaration because A is an incomplete type at that point;
> others (e.g. Intel Windows compiler, VC++ 6, Borland) are happy, provided
> class A has been defined before the template is instantiated. Which is
> correct?

I'm not sure. I cannot even find the place where it says that members
of a class must have complete type.

However, members of a class template do not need to have a complete
type. Otherwise, it would not be possible to define a member whose
type is a template parameter.

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Adam Peterson <ahp6@email.byu.edu>
Date: Mon, 3 Dec 2001 00:03:46 GMT
Raw View
"David Crocker" <dcrocker@imsltd.com> wrote in message
news:3c07c8fb$0$8507$ed9e5944@reading.news.pipex.net...
> In trying to generate portable C++ code from a specification, we have come
> across some code fragments to do with incomplete types that are accepted
by
> some compilers and not others. Can anyone conform the correct behaviour
and
> point me to the relevant clauses in the standard?

I assume you are referring to the correct behavior of the compiler, and not
the program.


> class A;   // forward declaration
> ...
> ... static_cast<A*>(0) ...  // null pointer of type A*
> ...
> class A{  // declaration of class A
> ...
> }
>

The above is well-formed (from what I can see).  The relevant section of the
standard is 3.2, specifically paragraph 4.


> class A;  // forward declaration
>
> template <class X> class B {
> { A myvar;
> ...
> };
>
> class A {
> ...
> }
>
> ... B<int> ...

The above is ill-formed, as a consequence of the definition of 'myvar'.
Section 3.1 paragraph 6:
A program is ill-formed if the definition of any object gives the object an
incomplete type (3.9).


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 3 Dec 2001 10:07:30 GMT
Raw View
"David Crocker" <dcrocker@imsltd.com> wrote in message
news:3c07c8fb$0$8507$ed9e5944@reading.news.pipex.net...
> In trying to generate portable C++ code from a specification, we have come
> across some code fragments to do with incomplete types that are accepted
by
> some compilers and not others. Can anyone conform the correct behaviour
and
> point me to the relevant clauses in the standard?
>
> First fragment:
>
> class A;   // forward declaration
> ...
> ... static_cast<A*>(0) ...  // null pointer of type A*

Pointers to incomplete types are themselves complete, so this is fine.

3.9.2p3:
"... Pointers to incomplete types are allowed although there are
restrictions on what can be done with them ..."

> Second construct:
>
> class A;  // forward declaration
>
> template <class X> class B {
> { A myvar;
> ...
> };

A is a non-dependent name, so is resolved at the point of definition of the
template.

14.6.3p1:
"Non-dependent names used in a template definition are found using the usual
name lookup and bound at the point they are used."

This template definition defines the member myvar to be of type A. This is
ill-formed, since A is an incomplete type at this point.

3.1p6:
"A program is ill-formed if the definition of any object gives the object an
incomplete type"

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]