在类中使用模板参数中的typename

  • 本文关键字:参数 typename c++
  • 更新时间 :
  • 英文 :

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