在以下示例中:
template<typename T>
struct MyList {
typedef std::list<T> type1;
};
template<typename T>
class MyList2 {
typename MyList<T>::type1 type2;
};
Run Code Online (Sandbox Code Playgroud)
我认为 type1 和 type2 都是依赖名称,因为它们的类型都依赖于模板参数。但是,为什么第一个被认为是非依赖的,因为我可以使用typedef
它?
在 C++ 术语中,从属名称是其语法属性依赖于模板参数的名称。
在 C++ 中,名称可以表示很多不同的含义,并且可以使用名称的语法位置取决于该名称的某些属性。为了理解X x;
要做什么,编译器需要知道X
程序中此时的内容。如果X
命名一个类型,那么这就是声明一个名为 的变量x
。编译器不需要了解有关 的所有内容X
,但从语法上讲,为了开始理解该文本,编译器确实需要知道此处X
命名了一个类型。
std::list
是类模板的名称;编译器可以很容易地看到这一点,因为这就是它的声明方式。它不需要有声明的正文;template<typename T> class list;
足够了。std::list<T>
是类模板的实例化,因此仅从声明中,编译器就知道这是类型的名称。
然而,MyList<T>::type1
现在需要的不仅仅是MyList
模板的声明。它需要实际实例化该模板。如果T
本身是当前代码的模板参数(如 的情况MyList2
),则在最初编译代码时进行实例化是不可能的。该实例化必须被延迟,直到MyList2
它本身被赋予一个具体的T
工作对象。
但编译器仍然必须理解这段代码:typename MyList<T>::type1 type2;
。为此,需要了解MyList<T>::type1
实际情况。无需实例化MyList<T>
.
这就是为什么你必须告诉它它是一个typename
.