Re: instantiating a template on an incomplete type?
On Jun 12, 6:47 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
[snip]
As for the remaining
question why a member declaration of a class requires a complete type,=
so
far I only have [9.2/2]:
A class is considered a completely-defined object type (3.9) (or
complete type) at the closing } of the class-specifier.
It seems hard to be complete with members of incomplete type.
Hm.
struct Foo;
struct Bar { Foo blah(); }; // Is OK :-)
At this point an object of type Bar can be instantiated, it's a complet=
e
type.
But the member routine Bar::blah cannot be called, so a complete type c=
an
have
members of incomplete type -- not hard at all! :-)
It's just that they cannot be used, and a member variable Bar::m of
incomplete type is used as soon as a Bar object is instantiated, or
copied, whatever.
The problem seems therefore to be why a member variable Bar::m is
considered used just by being declared, as opposed to the Bar::blah
routine. I don't know. Testing with g++ and MSVC it doesn't seem to hav=
e
anything to do with automatically generated special member routines tha=
t
might use a Bar::m.
Alternatively it may be that somewhere the standard spells out or
implicitly requires that a member variable (as opposed to routine) be o=
f
complete type?
I found [9.2/8]:
Non-static (9.4) members that are class objects shall be objects of
previously defined classes. In particular, a class cl shall not conta=
in an
object of class cl, but it can contain a pointer or reference to an o=
bject
of class cl. When an array is used as the type of a nonstatic member =
all
dimensions shall be specified.
So this requires non-static data members of class type to have a type
previously _defined_ (not just declared).
In other words, in a class definition, (non-static) data members must
have complete types After all, an incomplete type is nothing more than
a type that has been declared but not (yet) defined..
I still cannot find a clause that explicitly says that member specificati=
ons
of non-static data members form a context where a complete type is
required. (Maybe, it's false. Maybe incomplete function types -- do those
exist? -- are allowed. Or is it that T* is considered incomplete if T is
incomplete and T* is allowed?)
I think the existing wording is explicit enough. To answer your
questions: a pointer or reference to an incomplete type - is a
complete type. Just as a class template instantiated with an
incomplete type - is itself a complete type. So in this case, there is
no issue about the data member's completeness:: the std::vector<xyz>
is a complete type, even if the xyz class is not.
Moreover, the declaration of the member template inside the class
definition - instantiates only the -declarations- of the class
template, and none of its methods or data members. And as I once
pointed out, there is no possibility of undefined behavior unless
there is behavior. And without program code or program data, there is
no behavior.
Now, by the time the std::vector's data members and methods are
instantiated - the xzy class will be complete. So the question boils
down to: what is a template "component"? If one interprets component
to be the instantiated data members and methods of a template, then
std::vector<xyz> member should be fine.
Finally, the issue of Standard Libary containers and type completeness
- becomes even less clear if the enclosing class is itself a class
template. At which point is the class template complete in relation to
its member template?
Greg