Reputation: 732
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
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