You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by "Martin Sebor (JIRA)" <ji...@apache.org> on 2006/02/20 22:14:27 UTC

[jira] Commented: (STDCXX-152) error instantiating std::map on an incomplete type

    [ http://issues.apache.org/jira/browse/STDCXX-152?page=comments#action_12367079 ] 

Martin Sebor commented on STDCXX-152:
-------------------------------------

Copied from Rogue Wave QA incident #24464:

****Created By: sebor @ Jan 10, 2001 04:58:50 PM****
Subject: Re: Error 239: A class/union shall not contain a member with incomplete type.
Date: Wed, 10 Jan 2001 11:58:48 -0800
From: Alain Miniussi <al...@cup.hp.com>
Organization: HP
To: Martin Sebor <se...@roguewave.com>
CC: barry@uksr.hp.com, Dennis Handly <dh...@cup.hp.com>
References: 1

Martin, I wonder if you already had to deal with that issue, and
what you think about it.

Barry Levie wrote:
>
> Alain,
> Dennis suggested that you might be able to help. I have included a copy
> of the previous emails to save you having to search back through the
> acxx mail messages.
>
> Thanks
>
> Barry
>
> Hi,
>
> I wonder if some one could be so kind as to improve on and confirm my
> answer that this is a user error. (Of course I may have got it wrong.
> :-))

That's a tricky question :-)

First, the problem is the
set<X>::iterator f();

that requires instantiation of set<X>, to illustrate the problem:
----------------------
// case 1:
template<class T>
struct Cont1 {
   T* t;
   typedef int iter;
};

struct Str1 {
   Cont1<Str1>::iter f();
};

// case 2:
template<class T>
struct Cont2 {
   T t;
   typedef int iter;
};

struct Str2 {
   Cont2<Str2>::iter f();
};

-----------------------

where Cont<n> and Str<n> stands for set and X respectively.

Str1 is ok since Cont1 does not need a completly defined T,
Str2 is not since it requires a completely defined T.

Now, the library can (but are they allowed to ?) choose to
implement set and  set::iterator so that it looks like 1 or 2.

All compiler agree that 1 is good and 2 is bad, but some libraies
manage to implement set like 1. RW seems to implement it as in
2 (ie, instantiating set<X> requires a complete X).

Martin, can you confirm that this explanation is correct, and tell
if it is a known issue ? or if the standard tells something about it ?

Thanks,

Alain

> Thanks
>
> Barry
>
>  A.03.30
>
> $ more fii.c
> #include <set>
>
> class Y  {
> };
> class X {
>   X():mep(new set<X>()),me(*mep){}
>   set<X>::iterator f();
>   set<X> *mep;
>   set<X>  &me;
> };
>
> Error 239: "/opt/aCC/include/tree", line 140 # A class/union shall not
> contain
>     a member with incomplete type.
>             Value        value_field;
>                          ^^^^^^^^^^^
> Error 239: "/opt/aCC/include/tree", line 140 # A class/union shall not
> contain
>     a member with incomplete type.
>             Value        value_field;
>                          ^^^^^^^^^^^
> Error 537: "/opt/aCC/include/tree", line 140 # Cannot create a 'X'
> object;
>     class X has only been seen as an incomplete declaration.
>             Value        value_field;
>                          ^^^^^^^^^^^
>
> I believe that despite the fact that it compiles with gcc 2.9 its a user
>
> error.
>
> Due to
> http://www.hp.com/esy/lang/cpp/tguide/index.html
> 3.4.33 Templates - Declaring a Variable of an Incomplete Type Disallowed
>
> and the fact that
>
> The ansi standard describes the point of instantiation.
> "14.6.4.1(3) says the point of instantiation  immediately precedes the
> declaration or definition that refers to the specialization."
>
> My example seemed more straight forward.
>
> #include <set>
> using namespace std;
>
> #ifdef USERERROR
> class Y ;
> #else
> class Y{};
> #endif
> class X {
> typedef set<Y, less<Y>, allocator<Y> > set_type;
> set_type   sd;
> set_type::iterator sdi ;
>
> };
>
> ======================================================
> Dennis Handly wrote:
> >I wonder if some one could be so kind as to improve on and confirm my
> >answer that this is a user error.
> Barry
>
> I think the compiler is correct.
> You can't use X inside itself unless a pointer, or used in a static
> data member.
>
> #include <set>
> class X {
>   X() : mep(new set<X>),me(*mep){}
>   set<X>::iterator f();
>   set<X> *mep;
>   set<X> &me;
> };
>
> Even -AA fails the same way.
>
> >My example seemed more straight forward.
>
> And pretty obvious.
>
> ============================================================
> Sorry I am back again on this topic.
>
> Dennis Handly wrote:
>
> ....
>
> >
> > I think the compiler is correct.
> > You can't use X inside itself unless a pointer, or used in a static
> > data member.
> >
> > #include <set>
> > class X {
> >   X() : mep(new set<X>),me(*mep){}
> >   set<X>::iterator f();
> >   set<X> *mep;
> >   set<X> &me;
> > };
> >
> > Even -AA fails the same way.
>
> It seems that in rb_tree gcc uses a template for  _Rb_tree_node while RW
>
> uses a struct which is why it compiles ok with gcc. The customer says
> his
> third party STL compiles ok with our aCC compiler, so guess this could
> be
> for the same reason.
> Is it worth raising a ER or do we just put this down to an
> implementation
> difference.
>
> Regards
>
> Barry
>
> gcc
>
> template <class _Key, class _Compare = less<_Key>,
>           class _Alloc = allocator< _Key >  >
>
> template <class _Key, class _Value, class _KeyOfValue, class _Compare,
>           class _Alloc = allocator< _Value >  >
> class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc> {
>   typedef _Rb_tree_base<_Value, _Alloc> _Base;
> protected:
>   typedef _Rb_tree_node_base* _Base_ptr;
>   typedef _Rb_tree_node<_Value> _Rb_tree_node;
> .....
>
> template <class _Value>
> struct _Rb_tree_node : public _Rb_tree_node_base
> {
>   typedef _Rb_tree_node<_Value>* _Link_type;
>   _Value _M_value_field;
> }
>
> and with RW we have
>
> template <class Key, class Value, class KeyOfValue,
>  class Compare, class Allocator>
> class rb_tree
>  {
> ...
> struct rb_tree_node
>  {
> ...
>  Value value_field;
>  };
>
> ============================================================
>
> Dennis Handly wrote:
> > I think the compiler is correct.
> > You can't use X inside itself unless a pointer, or used in a static
> > data member.
> > #include <set>
> > class X {
> >   X() : mep(new set<X>),me(*mep){}
> >   set<X>::iterator f();
> >   set<X> *mep;
> >   set<X> &me;
> > };
>
> >It seems that in rb_tree gcc uses a template for _Rb_tree_node while RW
>
> >uses a struct which is why it compiles ok with gcc. The customer says
> his
> >third party STL compiles ok with our aCC compiler, so guess this could
> be
> >for the same reason.
>
> I'm not sure why it makes a difference.
>
> >Is it worth raising a ER or do we just put this down to an
> implementation
> >difference.
> Barry
>
> Let Alain look at it when he gets back.
>
> Perhaps we don't handle 14.6.4.1(1) (last sentence) right.
> I.e. is the point of instantiation the place in namespace scope after
> the use of the "me" reference, which would be after class X??
>
> =====================================================
> gcc
> template <class _Key, class _Compare = less<_Key>,
>           class _Alloc = allocator<_Key > >
> template <class _Key, class _Value, class _KeyOfValue, class _Compare,
>           class _Alloc = allocator<_Value > >
> class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc> {
>   typedef _Rb_tree_base<_Value, _Alloc> _Base;
> protected:
>   typedef _Rb_tree_node_base* _Base_ptr;
>   typedef _Rb_tree_node<_Value> _Rb_tree_node;
> .....
>
> template <class _Value>
> struct _Rb_tree_node : public _Rb_tree_node_base {
>   typedef _Rb_tree_node<_Value>* _Link_type;
>   _Value _M_value_field;
> }
>
> and with RW we have
> template <class Key, class Value, class KeyOfValue,
>  class Compare, class Allocator>
> class rb_tree {
> ...
> struct rb_tree_node {
> ...
>  Value value_field;
>  };
****Modified By: sebor @ Jan 10, 2001 05:02:21 PM****
Subject: Re: Error 239: A class/union shall not contain a member with incomplete type.
Date: Wed, 10 Jan 2001 17:01:48 -0700
From: Martin Sebor <se...@roguewave.com>
Organization: Rogue Wave Software, Inc.
To: Alain Miniussi <al...@cup.hp.com>
CC: barry@uksr.hp.com, Dennis Handly <dh...@cup.hp.com>
References: 1 , 2

Alain Miniussi wrote:
>
> Martin, I wonder if you already had to deal with that issue, and
> what you think about it.

I've seen the question(s) on cxx-dev but I don't really consider it to be a
defect in the library. The implementation is perhaps less robust than it could
be (due to the fact that __rb_tree<> refers to __rw_rb_tree_node<>::_C_link_t
and that __rw_rb_tree_node<> contains as a member a value of the incomplete
type). <continue below>

...
> > I wonder if some one could be so kind as to improve on and confirm my
> > answer that this is a user error. (Of course I may have got it wrong.
> > :-))
>
> That's a tricky question :-)
>
> First, the problem is the
> set<X>::iterator f();
>
> that requires instantiation of set<X>, to illustrate the problem:
> ----------------------
> // case 1:
> template<class T>
> struct Cont1 {
>     T* t;
>     typedef int iter;
> };
>
> struct Str1 {
>     Cont1<Str1>::iter f();
> };
>
> // case 2:
> template<class T>
> struct Cont2 {
>     T t;
>     typedef int iter;
> };
>
> struct Str2 {
>     Cont2<Str2>::iter f();
> };
>
> -----------------------
>
> where Cont<n> and Str<n> stands for set and X respectively.
>
> Str1 is ok since Cont1 does not need a completly defined T,
> Str2 is not since it requires a completely defined T.
>
> Now, the library can (but are they allowed to ?) choose to
> implement set and  set::iterator so that it looks like 1 or 2.
>
> All compiler agree that 1 is good and 2 is bad, but some libraies
> manage to implement set like 1. RW seems to implement it as in
> 2 (ie, instantiating set<X> requires a complete X).
>
> Martin, can you confirm that this explanation is correct, and tell
> if it is a known issue ? or if the standard tells something about it ?

Yes, I think the example illustrates what's happening here. 17.4.3.6
[lib.res.on.functions], p2 enumerates library cases with undefined behavior:

-2- In particular, the effects are undefined in the following cases:
...
-if an incomplete type (basic.types) is used as a template argument when
instantiating a template component.

I think it should be possible to implement the containers such that your example
compiles but I have a feeling that the change might have an effect on the ABI of
the library (not the binary itself, but perhaps the binary of some 3rd party
library that instantiates __rb_tree).

I have created a PR #24464. It might get addressed in the next major release of
the library.

Regards
Martin


> error instantiating std::map on an incomplete type
> --------------------------------------------------
>
>          Key: STDCXX-152
>          URL: http://issues.apache.org/jira/browse/STDCXX-152
>      Project: C++ Standard Library
>         Type: Improvement
>   Components: 23. Containers
>     Versions: 4.1.2, 4.1.3
>  Environment: all
>     Reporter: Martin Sebor

>
> From http://mail-archives.apache.org/mod_mbox/incubator-stdcxx-user/200602.mbox/%3c20060215231134.6717.qmail@web82211.mail.mud.yahoo.com%3e:
>   I am trying to use Boost built using stdcxx on Solaris. I was able to build the date_time
> library but when I try to compile a test program I end up with errors related to incomplete
> types. I have narrowed the issue to the following code
>    
>   #include <map>
> #include <string>
>   using namespace std;
>   template <class T>
> struct C {
>      typedef multimap<T,C> maps;
>      typedef typename maps::value_type value_type;
> };
>    
>   int main () {
>   C<std::string> c;
> }
>   When I compile using the default Sun CC libraries or rwtools7_std or stlport4, the code
> compiles fine. But when I compile using stdcxx, I end up with the following errors.
>    
>   "/opt/idev3/dbapatla/apache-stdcxx-4.1.3/include/rw/_pair.h", line 55: Error: In this declaration
> "second" is of an incomplete type "C<std::string>".
> "/opt/idev3/dbapatla/apache-stdcxx-4.1.3/include/rw/_tree.h", line 86:     Where: While specializing
> "std::pair<const std::string, C<std::string>>".
> "/opt/idev3/dbapatla/apache-stdcxx-4.1.3/include/rw/_tree.h", line 86:     Where: Specialized
> in __rw::__rw_rb_tree_node<std::allocator<std::pair<const std::string, C<std::string>>>,
> std::pair<const std::string, C<std::string>>, std::string, __rw::__select1st<std::pair<const
> std::string, C<std::string>>, std::string>>.
> "/opt/idev3/dbapatla/apache-stdcxx-4.1.3/include/rw/_tree.h", line 259:     Where: Specialized
> in __rw::__rb_tree<std::string, std::pair<const std::string, C<std::string>>,
> __rw::__select1st<std::pair<const std::string, C<std::string>>, std::string>,
> std::less<std::string>, std::allocator<std::pair<const std::string, C<std::string>>>>.
> "/opt/idev3/dbapatla/apache-stdcxx-4.1.3/include/map", line 323:     Where: Specialized in
> std::multimap<std::string, C<std::string>, std::less<std::string>, std::allocator<std::pair<const
> std::string, C<std::string>>>>.
> "test2.cpp", line 9:     Where: Specialized in C<std::string>.
> "test2.cpp", line 13:     Where: Specialized in non-template code.
> 1 Error(s) detected.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira