This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Forward declaration and usage rules


Tony Simons <ajhs@dcs.shef.ac.uk> writes:

> I have compiled C++ code using g++ version 2.95.3 that seems to allow forward 
> usage of *value*-types in a class declaration, against my expectations.  I only 
> expected to be allowed forward usage of pointer-types and reference-types.  Note 
> that this only applies to forward uses in the *declaration* - I have to include 
> full headers before I can compile *definitions" of the member functions.
> 
> Does C++ allow arbitrary use of forward-declared types in class declarations?  
> If not, does g++ relax these rules on forward declarations?  Would my code 
> therefore not port to other C++ compilers?  Has the C++ standard changed 
> recently to allow forward use of value-types inside class declarations?  Or is 
> this actually a bug in g++? 
> 
> My actual example is a library of Real, Imaginary and Complex numbers (all 
> value-types), for which mutually-recursive definitions would be very useful, if 
> this style is eventually kosher and portable.  A cut-down model of the 
> phenomenon is given below, which I have also tested:
> 
> --Tony Simons
> 
> 
> // in file A.h =========================
> 
>  class B;  	// forward declaration
>  
>  class A {
>  public:

The fact that this is inside a class decl is irrelevant.

>  	A::A(float x);
>  	B foo(int x) const;	// Unexpectedly OK!  Returns a B value
>   	B bar(B b) const;	// Unexpectedly OK!  Accepts a B value too

The limitation on incomplete types is that one cannot create an object
    of that type, or take the size of that type. Here you do niether
    of those; you merely use the type in a declaration. This is
    well-formed. See 3.9 .

>  private:
>  	float f;
>  };
>  
>  #include "B.h"			// the full include is required here...
>  
>  inline A::A(float x) : f(x) {}
>  
>  inline B A::foo(int x) const {
>  	return B(x);		// ...for this to compile, and also...

Here you create an object of type B. Therefor B must be complete at
    this point.

>  }
>  
>  inline B A::bar(B b) const {
>  	return B(b);		// ...for this to compile, as expected.
>  }

gcc 3.4 and comneau both report only one error for your code:

tn.cc:44: error: 'main' must return 'int'
tn.cc:44: error: return type for 'main' changed to 'int'

which has nothing to do with you question and is trivially fixed.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]