//A.h
template <class T>
class A
{
public:
typename T::Type x; //(1) compile time error: C2039 'Type': is not a member of 'B'
void f();
};
template <class T>
void A<T>::f()
{
typename T::Type x1; //(2) but no errors here
}
//B.h
#include "A.h"
class B : public A<B>
{
public:
using Type = int;
};
//main.cpp
#include "B.h"
int main()
{
B x;
}
为什么(1(中有错误,但(2(中没有错误?如何在类中存储类型为typename T::Type
的变量并编写类似func(typename T::Type)
的函数?
我不知道为什么要做这个类设计,我不想改变代码中的类层次结构或模板参数,因为有很多从a继承的类,代码很混乱。因此,请不要以这种方式提出建议。
附言:很抱歉没有弄清楚问题名称,但我想不出更好的了。
当您定义class B : public A<B>
时,类B
没有定义,但您试图在A中使用这个类。此时,编译器不知道是否会有using Type = int;
的定义。
gcc提供了一个可读性更强的错误消息:;无效使用不完整类型"class B";
void A<T>::f()
永远不会被实例化,因此您不会看到错误消息。
坏消息是:在这种情况下,你没有机会做任何类型的正向声明,因为你有一个完整的循环依赖。
class B : public A<B>
CCD_ 7在这一点上是不完整的。目前还不知道它是否有一个Type
成员。因此A::x
的实例化失败。
相比之下,A<T>::f()
从未被实例化。如果您确实实例化了它,那么当B
是一个完整的类型时,很可能会发生这种情况,所以B::Type
应该已经是已知的。
由于定义中的循环性,您无法做到这一点——在定义了B
之前,不能定义A<B>
,在定义A<B>
之后,才能定义B
。
你可以做的是添加一个间接级别,通过一个";性状";独立于B
的最终定义的类。
示例:
template <typename T>
struct traits{};
template <class T>
class A
{
public:
typename traits<T>::Type x;
};
class B;
template <>
struct traits<B>
{
using Type = int;
};
class B : public A<B>
{
public:
using Type = typename traits<B>::Type;
};
int main()
{
B x;
}