Article View: gnu.g++.help
Article #94Out-of-order instantiation of templates and incomplete types
From: Nate Osgood
Date: Sat, 08 Aug 1992 02:33
Date: Sat, 08 Aug 1992 02:33
108 lines
4691 bytes
4691 bytes
I've run into a curious behavior pattern (possibly a bug?) of g++, and
was wondering if anyone else here might know if there is an easy fix
to stop this behavior (or at least one less gross than that described
below). Alternatively, since I haven't played around too much with
templates, I hope that maybe I'm making some stupid mistake that can
be trivially correct.
I have two class templates (I've called them classes "A" and "B")
which are consecutive in an include file. Class B actually contains
within it a field of type class A (with an associated parameterized
type), so given the standard rules of ordering type definitions, it
must follow class A in the file (so that the compiler knows how big
that field is when compiling class B). Class A does not contain a
field of type B, but DOES contain a textual reference to class B in
one of the member function prototypes.
The template definitions compile fine. The problem is that when I
actually try to declare an object of type class A, it seems there is
some type of non-standard ordering in the processing of the type
definitions, such that the compiler reports that the field of type
class A in class B has an "incomplete type" (which seems to usually
mean that its definition is not complete). Note that this is DESPITE
the fact that the definition of class A TEXTUALLY precedes the
definiton of class B in the file.
I've included the code here, since I think it shows the problem more
clearly than I can express it:
----------------------
template<class Contents> class A
{
public:
A();
foo( B<Contents> *); /* Here's the TEXTUAL reference to class B */
};
template<class Contents> class B
{
A<Contents> Next; /* Here's the field that uses class A */
};
/* typedef B<int> foo; */ /* <= If we uncomment this, we will be
"pre-instantiating" B with the
appropriate type , and the file
will compile fine. */
/* Here's the use that normally forces instantiation */
A<int> table;
----------------------
My vague sense of what is happening is that when I declare an object
of class A, the compiler tries to instantiate the template for class
A. When it sees the textual reference to class B in that template, it
immediately tries to instantiate class B's template (and process that
definition). Since it is still not done processing class A at this
point, and because class B needs to be processed AFTER class A, the
compiler issues the complaint about the incomplete type (since A is
incomplete when class B is being processed). Note that in "normal"
compilation behavior, class B would ALWAYS be compiled AFTER class A,
so this problem would never arise. It is my guess that the template
instantiation mechanism is imposing a different order of processing
the declarations, and thus we see the difference in error messages.
I came up with a really kludgey workaround to this based on the above
tentative diagnosis of the problem: I basically FORCE instantiation of
class B BEFORE any declarations (I know, this is counterintuitive, but
my theory is that doing B first forces B's instantiation to wait for
A's instantiation to be finished (since there is an instantiation of
type A in the field for type B). When A's instantiation then tries to
instantiate B, it realizes that this is already in progress and
continues on. Again this is just a guess, although it does roughly
fit the behavior observed).
My kludgey work-around strategy works as long as the instantiation is
done with the same type as will be used to instatiate the class B when
it is used by A. (So we sort of pre-instantiate it). However, this
is clearly gross -- we need to explicitly "pre-instantiate" all the
appropriate referenced classes before they are used, with ALL of the
types they will EVER be instantiated with. Does anyone have a better
workaround?
Any help greatly appreciated!
Nate Osgood
--
-------------------------------------------------------------------------------
Nate Osgood | ARPA: hacrat@catfish.lcs.mit.edu
CS Graduate Student |
MIT LCS Room NE43-636 | UUCP: ...!uunet!catfish.lcs.mit.edu!hacrat
Technical Details
Message-ID:
<1992Aug8.023317.8117@mintaka.lcs.mit.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!usc!sol.ctr.columbia.edu!destroyer!gumby!yale!mintaka.lcs.mit.edu!CATFISH.LCS.MIT.EDU!hacratShow Full Headers
Complete Article Headers
Newsgroups: gnu.g++.help Path: arc1-ca.pugleaf.net!sparky!uunet!usc!sol.ctr.columbia.edu!destroyer!gumby!yale!mintaka.lcs.mit.edu!CATFISH.LCS.MIT.EDU!hacrat From: hacrat@CATFISH.LCS.MIT.EDU (Nate Osgood) Subject: Out-of-order instantiation of templates and incomplete types Message-ID: <1992Aug8.023317.8117@mintaka.lcs.mit.edu> Sender: news@mintaka.lcs.mit.edu Organization: MIT Laboratory for Computer Science Date: Sat, 8 Aug 1992 02:33:17 GMT Lines: 108