using a class inside a class.

P

phil.pellouchoud

I did some searching online and i couldn't find anything in reference
to this.

I am using MinGW, gcc 4.3 and am having the following compilation
issue:

class CFoo
{
public:
...
private:
std::list<CFoo> m_children;
};

The complaint from the compiler looks like this:

c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In instantiation of
'__gnu_cxx::_SGIAssignableConcept<CFoo>':
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo,
std::allocator<CFoo> >'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:216: error:
'__gnu_cxx::_SGIAssignableConcept<_Tp>::__a' has incomplete type

So, basically, I think what it's saying is that it doesn't know how to
build the class because CFoo hasn't been defined by the time it's
trying to create it (i.e. incomplete type). I tried adding
"std::list<class CFoo>" as well, but that didn't work either. This
compiles on visual studio with some warnings.

I can make this work by making it "std::list<CFoo*>", but I'm
wondering if there's a way to get this to work as defined.

thanks for listening.

-phil
 
J

Jim Langston

I did some searching online and i couldn't find anything in reference
to this.

I am using MinGW, gcc 4.3 and am having the following compilation
issue:

class CFoo
{
public:
...
private:
std::list<CFoo> m_children;
};

The complaint from the compiler looks like this:

c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In instantiation of
'__gnu_cxx::_SGIAssignableConcept<CFoo>':
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo,
std::allocator<CFoo> >'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:216: error:
'__gnu_cxx::_SGIAssignableConcept<_Tp>::__a' has incomplete type

So, basically, I think what it's saying is that it doesn't know how to
build the class because CFoo hasn't been defined by the time it's
trying to create it (i.e. incomplete type). I tried adding
"std::list<class CFoo>" as well, but that didn't work either. This
compiles on visual studio with some warnings.

I can make this work by making it "std::list<CFoo*>", but I'm
wondering if there's a way to get this to work as defined.

thanks for listening.

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.

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

phil.pellouchoud

Here's exactly what i get when I try to compile that code:

C:\>type foo.cpp
#include <list>

class CFoo
{
private:
std::list<CFoo> m_children;

};

int main()
{
CFoo Foo;

}
C:\>gcc -v
Using built-in specs.
Target: i386-pc-mingw32
Configured with: ../gcc-4.3.0/configure --prefix=/mingw --disable-nls
--enable-languages=c,c++,fortran,objc,obj-c++,ada,
java --disable-win32-registry --disable-sjlj-exceptions --enable-
libstdcxx-debug --enable-version-specific-runtime-libs
--with-gmp=/mingw/src/gcc/gmp-mpfr-root --with-mpfr=/mingw/src/gcc/gmp-
mpfr-root --enable-libgcj --enable-concept-checks
--enable-shared
Thread model: win32
gcc version 4.3.0 (GCC)

C:\>gcc -o foo foo.cpp
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In instantiation of '__gnu_cxx::_S
GIAssignableConcept<CFoo>':
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo, std:
:allocator<CFoo> >'
foo.cpp:6: instantiated from here
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:216: error: '__gnu_cxx::_SGIAssigna
bleConcept<_Tp>::__a' has incomplete type
foo.cpp:4: error: forward declaration of 'class CFoo'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In member function 'void __gnu_cxx
::_SGIAssignableConcept<_Tp>::__constraints() [with _Tp = CFoo]':
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo, std:
:allocator<CFoo> >'
foo.cpp:6: instantiated from here
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:208: error: using invalid field '__
gnu_cxx::_SGIAssignableConcept<_Tp>::__a'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:209: error: using invalid field '__
gnu_cxx::_SGIAssignableConcept<_Tp>::__a'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:209: error: using invalid field '__
gnu_cxx::_SGIAssignableConcept<_Tp>::__a'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo, std:
:allocator<CFoo> >'
foo.cpp:6: instantiated from here
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:210: error: using invalid field '__
gnu_cxx::_SGIAssignableConcept<_Tp>::__a'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In member function 'void __gnu_cxx
::_SGIAssignableConcept<_Tp>::__const_constraints(const _Tp&) [with
_Tp = CFoo]':
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:210: instantiated from 'void __gn
u_cxx::_SGIAssignableConcept<_Tp>::__constraints() [with _Tp = CFoo]'
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
stl_list.h:420: instantiated from 'std::list<CFoo, std:
:allocator<CFoo> >'
foo.cpp:6: instantiated from here
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h:214: error: using invalid field '__
gnu_cxx::_SGIAssignableConcept<_Tp>::__a'

C:\>
 
I

Ian Collins

Here's exactly what i get when I try to compile that code:

C:\>type foo.cpp
#include <list>

class CFoo
{
private:
std::list<CFoo> m_children;

};

int main()
{
CFoo Foo;

}

C:\>gcc -o foo foo.cpp
c:\mingw\bin\../lib/gcc/i386-pc-mingw32/4.3.0/include/c++/bits/
boost_concept_check.h: In instantiation of '__gnu_cxx::_S
GIAssignableConcept<CFoo>':

<snip>

Looks like your compiler isn't configured correctly, try a gcc group.
 
K

kwikius

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.

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.

IMO gcc is correct. You could have a list of pointers or refs to CFoo
but not recursive types. One workaround *may* be to use a typedef
alias for CFoo. That may fool gcc, but I think its technically correct
to call this an error.

regards
Andy Little
 
I

Ian Collins

kwikius said:
IMO gcc is correct. You could have a list of pointers or refs to CFoo
but not recursive types. One workaround *may* be to use a typedef
alias for CFoo. That may fool gcc, but I think its technically correct
to call this an error.
Why? The class declares m_children to be a list of CFoo. It does not
attempt to use any members of std::list that require a complete type.

In effect, it's just like writing

#include <list>

class X;

class CFoo
{
private:
std::list<X> m_children;
};

class X {};

int main()
{
CFoo Foo;
}

The complete class definition is not required until std::list's default
constructor is instantiated in main().
 
K

kwikius

Ian Collins said:
Why? The class declares m_children to be a list of CFoo. It does not
attempt to use any members of std::list that require a complete type.

Ah as to Why ... I Dunno. Hopefully someone of a more technical nature will
help out as to why. From the error messages gcc is using C++0x style Concept
checking.

Various things to try to diagnose the problem. Try some other dummy template
class than std::list.
If that succeeds then std::list is concept checking and wont allow itself to
be instantiated without a complete type or some such

There is presumably an option to turn it off . ..

regards
Andy Little
 
I

Ian Collins

kwikius said:
Ah as to Why ... I Dunno. Hopefully someone of a more technical nature will
help out as to why. From the error messages gcc is using C++0x style Concept
checking.
It does, doesn't it? I thought that was a little odd, I didn't think
gcc had built in boost libraries.
 
K

kwikius

Ian Collins said:
It does, doesn't it? I thought that was a little odd, I didn't think
gcc had built in boost libraries.

Ahha yes its not C++0x Concepts, its old style concept checking . Theres
bound to be an option to turn that off.
Probbably a macro somewhere

Its all legit AFAIK.
After all std::list may want to for example instantiate some private
template type of allocate<sizeof (T)>
when its constructed for which it would obviously need the complete type.

regards
Andy Little
 
I

Ian Collins

kwikius said:
Ahha yes its not C++0x Concepts, its old style concept checking . Theres
bound to be an option to turn that off.
Probbably a macro somewhere

Its all legit AFAIK.
After all std::list may want to for example instantiate some private
template type of allocate<sizeof (T)>
when its constructed for which it would obviously need the complete type.
True, but that only happens when a CFoo is created and fully declared.
 
J

Jim Langston

Ian said:
It does, doesn't it? I thought that was a little odd, I didn't think
gcc had built in boost libraries.

That had thrown me off also, the boost error messages on something that has
nothing to do with boost. I wonder if it's some compiler switch?
 
K

kwikius

Jim Langston said:
That had thrown me off also, the boost error messages on something that
has nothing to do with boost. I wonder if it's some compiler switch?

FWIW following gives something similar. The trick is to make some
dependency, which must be going on in the O.P.

#include <list>

template<typename T>
struct dummy : T{ };

struct CFoo {
dummy<CFoo> my_list;
};

int main()
{
CFoo foo;
}
 
J

James Kanze

Nothing standards conformant.
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.)

The current working draft still has basically the same words
(with an "unless specifically allowed" exception, for e.g.
shared_ptr). I believe, however, that it is the intent to
require an error here once concepts have been added to the
language.

G++ uses boost::concepts (or something derived from it, I'm
not sure) to generate errors in most of cases, rather than
letting the undefined behavior through.
 
J

James Kanze

Ahha yes its not C++0x Concepts, its old style concept
checking. Theres bound to be an option to turn that off.
Probbably a macro somewhere

It's off by default (but I always turn it on). To get it, you
need to define _GLIBCXX_CONCEPT_CHECKS, i.e. specify the option
-D_GLIBCXX_CONCEPT_CHECKS.
Its all legit AFAIK.
After all std::list may want to for example instantiate some private
template type of allocate<sizeof (T)>
when its constructed for which it would obviously need the complete type.

I don't think that there's any particular justification for this
particular class. The rule in C++-03 was general: only complete
types when instantiating a template, regardless. The committee
made no effort to second guess what implementors might or might
not want to do in specific cases.

As far as I know, there's also no movement to change this
particular rule (although some of the new classes, like
shared_ptr, are an explicit exception, and other rules have been
loosened---std::list will no longer require assignable, for
example).
 
I

Ian Collins

James said:
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?
 
K

Kai-Uwe Bux

With regard to std::list, no particular reason. The standard just requires
all types to be complete when used with the STL components. The committee
just did not include an exception for std::list, even though any straight
forward implementation of std::list that does not do something overly smart
or funny will work gracefully with incomplete types. (I consider it a
defect in the standard, but I think that is just me: the drafts for C++0X
have the same language.)

That had thrown me off also, the boost error messages on something that
has
nothing to do with boost. I wonder if it's some compiler switch?

[OT] Nope. It depends on how g++ and in particular the STL that ships with
it are built on your machine. If you make it with --enable-concept-checks,
you get those errors. If you disable concept-checks, std::list will behave
nicely with regard to incomplete types (although that is not guaranteed by
the standard nor by the g++ folks).


Best

Kai-Uwe Bux
 
J

James Kanze

James said:
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.)
 
J

James Kanze

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

Cynic

James said:
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.)

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
(Note that declaring the type as
"std::list< CFoo >* m_children" should work.)

this would create a pointer to a LIST?
and would it help then if the std::list is created outside the
class?
 
P

phil.pellouchoud

It's off by default (but I always turn it on). To get it, you
need to define _GLIBCXX_CONCEPT_CHECKS, i.e. specify the option
-D_GLIBCXX_CONCEPT_CHECKS.


I don't think that there's any particular justification for this
particular class. The rule in C++-03 was general: only complete
types when instantiating a template, regardless. The committee
made no effort to second guess what implementors might or might
not want to do in specific cases.

As far as I know, there's also no movement to change this
particular rule (although some of the new classes, like
shared_ptr, are an explicit exception, and other rules have been
loosened---std::list will no longer require assignable, for
example).

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

did the default behavior change in gcc 4.3? 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...

-phil
 

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

Forum statistics

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

Latest Threads

Top