c++ 依赖名称与非依赖名称

fivyi3re  于 2023-06-07  发布在  其他
关注(0)|答案(2)|浏览(177)

在以下示例中:

template<typename T>
struct MyList {
    typedef std::list<T> type1;
};

template<typename T>
class MyList2 {
    typename MyList<T>::type1 type2;
};

我认为type1和type2都是依赖名,因为它们的类型都依赖于模板参数。但是,为什么第一个被认为是非依赖的,因为我可以使用typedef

kg7wmglp

kg7wmglp1#

在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

k2arahey

k2arahey2#

虽然std::list<T>使用T,但它不依赖于T。只要包含<list>,名称std::list就存在。
另一方面,typename MyList<T>::type1 type2;确实依赖于T,因为如果不示例化MyList<T>,就无法知道type1是什么。这就是为什么你必须使用typename,因为语法默认情况下会将type1视为成员变量或成员函数,而不是类型。

相关问题