using a class inside a class.

I

Ian Collins

James said:
True, but that only happens when a CFoo is created and fully declared.

How's that? The class itself must be instantiated immediately,
in CFoo, since a non-static member variable requires a complete
type. Member functions (and static member variables) will not
be instantiated until used, but the compiler needs the class
itself in order to layout CFoo. And according to the
requirements of the standard, instantiating the class over an
incomplete type is undefined behavior. (The class instance of
std::list could contain something like
unsigned char buf[ sizeof(A) ] ;
for example, either directly, or in a member or base class.
Unlikely, but the standard explicitly leaves this up to the
implementation.)
Which would cause it to fail to compile in this case. If std::list only
contains pointers to its value type, then its size is known and it will
compile.

It's not uncommon for classes to have std::auto_ptr members which use
incomplete types.

I can see why this area needs some cleaning up in the new standard.
 
J

James Kanze

[...]
It's not uncommon for classes to have std::auto_ptr members
which use incomplete types.

It's undefined behavior, so there will be no such cases in
correct code. (Strangely enough, however, g++ doesn't seem to
cover this case in its concept checking. And of course,
typically, there won't be any reason for it not to work, at
least on machines where all object pointers have the same size
and representation.)
 
J

James Kanze

On Apr 29, 1:46 am, James Kanze <[email protected]> wrote:

[...]
[...]
did the default behavior change in gcc 4.3?

I don't know. The latest version I currently have installed
here is 4.1.0. (I really should install 4.3, but I haven't had
time as yet.)

I know that the g++ people are implementing a preliminary
version of concepts, which will change the way this is handled.
i seem to get it by default; and I don't know how to turn it
off. I did try doing a
#undefine _GLIBCXX_CONCEPT_CHECKS
at the top of the sample app:
---- cut here ----
#undef _GLIBCXX_CONCEPT_CHECKS
#include <list>
class CFoo
{
private:
std::list<CFoo> m_children;
};
int main()
{
CFoo Foo;
}
---- cut here ----
But i still get the same error. I would love to be able to
simply disable it if I could...

Just compile with an older version of g++. But why? It will be
a required error in the future, so you won't be able to upgrade
compilers, or us any other more recent compiler, if you do so.
The code is illegal today; it just happens to work with some
compilers, by chance, but even then, the compiler vendor doesn't
guarantee it.
 
I

Ian Collins

James said:
[...]
It's not uncommon for classes to have std::auto_ptr members
which use incomplete types.

It's undefined behavior, so there will be no such cases in
correct code. (Strangely enough, however, g++ doesn't seem to
cover this case in its concept checking. And of course,
typically, there won't be any reason for it not to work, at
least on machines where all object pointers have the same size
and representation.)
That's the bit I don't get - the compiler can't compile the class if the
size of a member is unknown, so why should this be undefined behaviour?
Implementation defined maybe, but undefined?
 
J

James Kanze

James Kanze wrote:
All I can tell you is I've done this exact same thing
in the past successfully in both Microsoft Visual C++
.net 2003 and DevC++. Here is something that compiles
sucessfully in Microsoft Visual C++ .net 2003:
#include <list>
class CFoo
{
private:
std::list<CFoo> m_children;
};
int main()
{
CFoo Foo;
}
No warnings, no errors.
That's what's so nice about undefined behavior. The fact that
it works doesn't prove anything.
I don't know why your version of gcc is complaining, I don't
think it should, AFAIK this is perfectly legal, although I
haven't read the standard on it.
§17.4.3.6/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.
A class is only a complete type after the closing braces, so
your code has undefined behavior. (The standard could have
allowed incomplete types for certain specific cases, but it
didn't.)
But isn't the template component being instantiated in main
after the class is complete?
The class itself will be instantiated anytime it is used in
a context where a complete type is required. (How could it
be otherwise?) Class members (functions, static data
members) will be instantiated when (and only when) they are
used. Since only complete types can be used as member
variables, the class itself must be instantiated in CFoo.
(Note that declaring the type as "std::list< CFoo >*
m_children" should work.)
this would create a pointer to a LIST?

Yes. And since declaring a pointer to the type doesn't require
the type (i.e. the instantiation of std::list) to be complete,
it doesn't trigger instantiation of the template.
and would it help then if the std::list is created outside the
class?

Yes. As long as the type in question is complete whenever the
class is instantiated. The formal rules as to when something is
intantiated are fairly complex, but a rough approximation,
sufficient for most concerns, is simply that the class itself
will be instantiated anytime the compiler needs a complete type,
or something in the class, and the class members will be
instantiated anytime they are used.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top