首页 > 解决方案 > 两个模板类相互使用作为模板参数

问题描述

两个模板类可以互相使用作为模板参数,但是如果我使用在一个类范围内定义的任何东西,它就不能被编译。

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 抱怨:

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

它还涉及循环依赖吗?有没有一种可能的方法来解决它?

标签: c++templates

解决方案


gcc 的错误信息提供了更多信息:

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

这样做,让 gcc 高兴:

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> {};

这不是模板循环引用。第一个模板中唯一的引用是它自己的模板参数。仅仅因为它的模板参数恰好是命名B的,并且稍后定义了另一个具有相同名称的模板,不会使模板参数成为对另一个模板的引用。

就实际类而言,前向声明(如本例所示)使类之间的循环引用成为可能。


推荐阅读