Topic: Forward declaration of nested types (was mutual recursion: living with non-orthogonality)
Author: jamshid@ses.com (Jamshid Afshar)
Date: Wed, 1 Jun 1994 20:11:41 GMT Raw View
Redirected to comp.std.c++.
In article <2shbp1$r46@lamb.saltfarm.bt.co.uk>,
Tony Bass <aeb@saltfarm.bt.co.uk> wrote:
>How can one best live with the lack of orthogonality in C++ facilities?
>I first noticed the impossibility of
>
> class B;
> class A {
> B f(void);
> };
> class B {
> A g(void);
> };
>
>which my cfront-derived HP-UX compiler (and from the ARM I imagine any
>compiler) rejected. I then had similar problems with local typedefs,
That code is correct and allowed by Cfront 3.0.2 and g++ 2.5.5. Maybe
you haven't shown us the code that actually gave you an error and your
real code defined both member functions inline. While you can
*declare* a function as returning or taking an incomplete type (eg,
"class B;"), you cannot *define* the function until the compiler sees
the full type definition. If you want both functions to be inline,
you must move one of the member function definitions after the class
definitions. Btw, it's a good idea to declare the functions as inline
inside the class definition if you later define it inline outside the
class.
class B;
class A { inline B f(); };
class B { A f() { A r; return r; } };
inline B A::f() { B r; return r; }
> class A {
> typedef int Ai;
> int f(B::Bi b); // ??
> };
>
> class B {
> typedef int Bi;
> int g(A::Ai a); // OK
> };
>
>where it is possible to use a previously defined type, but I have not
>found any technique allowing a forward reference.
I seem to remember something about ANSI/ISO C++ allowing:
class A;
class A::N;
A* pa;
A::N* pn;
class A { int i; };
class A::N { /*...*/ };
but I'm not sure this has been accepted nor does it necessarily allow
your code which uses a nested typedef. I also seem to remember
something about forward definition of a template argument's nested
types:
template<class Container>
class Iter {
typedef Container::IterState; // new syntax: declares nested type
Container::IterState state;
//...
};
template<class T>
class LinkedList {
struct Node {/*...*/};
typedef Node* IterState;
//...
};
LinkedList<int> list;
Iter< LinkedList<int> > iter( &list );
Maybe the new typedef syntax will be extended to allow general
declarations of nested types:
class B;
class A {
typedef int Ai;
typedef B::Bi;
int f(B::Bi b);
};
class B {
typedef int Bi;
int g(A::Ai a); // OK
};
int B::f( B::Bi b ) {/*...*/}
>For the first example I would probably work around by trying to use
>non-member functions, perhaps with no disadvantage at all.
You should only have to do this if you have a broken compiler.
>For the
>second example, my workarounds tend to involve making something more
>global, to the detriment of good decoupling.
Making the nested typedefs global does not affect the coupling of the
classes. If anything, they would then be less coupled because the
classes do not need to know about each other. But, it would be nice
if there was a way to allow your code. Anyone know if any of the
accepted ANSI/ISO proposals would do it?
Jamshid Afshar
jamshid@ses.com