I have a number of situations where I need to mutually reference nested classes e.g.
class C1;
class C2;
// class C2::S; // not allowed by the standard
template <class T> class R
{
T* t = nullptr; // The only use of T as a data member is a T*
};
class C1
{
public:
class S
{
public:
R <C2::S> r; // Fails to compile because C2 is an incomplete type
};
};
class C2
{
public:
class S
{
public:
R <C1::S> r;
};
};
This fails because C2 is incomplete and at the point where it is used and so C2::S is not known to the compiler.
The question is in two parts:
There are a couple of 'obvious' solutions but I'm hoping not to have to use them:
I was expecting to be able to use a dummy class in place of C2::S and then map it to C2::S before using it but it appears you can't declare a class and then redefine it with 'using', e.g. the following doesn't work:
class Z; // Z first defined as a class
class C1
{
public:
class S
{
public:
R<Z> r;
};
};
class C2
{...}
using Z = C2::S; // Redefinition error (defining Z as a typedef vs. a class)
I've also tried with templates e.g.
template <class T> class TC1
{
public:
class S
{
public:
R <typename T::S> r;
};
};
template <class T> class TC2
{
public:
class S
{
public:
R <typename T::S> r;
};
};
using C1 = TC1 <TC2 <C1>>; // Error: C1 undeclared (or not in scope)
Regarding additions to the standard, I realize that allowing the use of incomplete types would never be acceptable as it would cause a lot of complexity e.g. in specifying what could and could not be used, or trying to define when different partially-defined versions of the same class are compatible or not.
I'm out of ideas. Any suggestions?
This isn't the usual situation where people wish they could write
class A::B;
instead of defining A
: you just want to have the nested classes refer to each other. That means that ordinary forward declarations work:
class C1
{
public:
class S;
};
class C2
{
public:
class S
{
public:
R <C1::S> r;
};
};
class C1::S
{
public:
R <C2::S> r;
};
Obviously this depends on R
not needing its template argument to be a complete type.