samm
samm

Reputation: 732

Two template classes use each other as template argument

Two template classes can use each other as template argument, but if I use anything defined in one class scope, it cannot be compiled.

template<class B> struct A {
    typedef A *pointer;
};
template<class A> struct B {
    //typedef A::pointer APtr;
    //using APtr = A::pointer;
    //APtr pa;
    A::pointer pa;
};

struct AA;
struct BB;
struct AA : public A<BB> {};
struct BB : public B<AA> {};

VS2017 complained:

1>c:\test.cpp(59): warning C4346: 'pointer': dependent name is not a type
1>c:\test.cpp(59): note: prefix with 'typename' to indicate a type
1>c:\test.cpp(60): note: see reference to class template instantiation 'B<A>' being compiled
1>c:\test.cpp(59): error C2061: syntax error: identifier 'pointer'
1>c:\test.cpp(59): error C2238: unexpected token(s) preceding ';'
1>c:\test.cpp(69): warning C4091: '': ignored on left of 'A<BB> *' when no variable is declared

Is it also involved circular dependency? Is there one possible way to fix it?

Upvotes: 0

Views: 280

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

gcc's error message is much more informative:

t.C:8:5: error: need ‘typename’ before ‘A::pointer’ because ‘A’ is a dependent scope
    8 |     A::pointer pa;
      |     ^
      |     typename 

And doing that, makes gcc happy:

template<class B> struct A {
    typedef A *pointer;
};
template<class A> struct B {
    //typedef A::pointer APtr;
    //using APtr = A::pointer;
    //APtr pa;
    typename A::pointer pa;
};

struct AA;
struct BB;
struct AA : public A<BB> {};
struct BB : public B<AA> {};

This is not a template circular reference. The only reference in the first template is to its own template parameter. Just because its template parameter happens to be named B, and there is another template defined with the same name, later, doesn't make the template parameter a reference to the other template.

And as far as the actual classes go, forward declarations, as in this case, make circular references between classes possible.

Upvotes: 1

Related Questions