我在这个网址上看了概况介绍
typename.htm
我意识到我不知道T::x可以代表什么类型。这是一段节选
template<class T> class A
{
T::x(y);
typedef char C;
A::C d;
}语句T::x(y)是不明确的。它可以是带有非局部参数y的函数x()的调用,也可以是变量y的声明,类型为T::x。C++将此语句解释为函数调用。为了让编译器将此语句解释为声明,您需要将关键字typename添加到它的开头。陈述A::C,d;是畸形的.类A也引用A,因此依赖于模板参数。必须将关键字typename添加到此声明的开头:
我想了解T::x类型的变量y是如何工作的,这可能意味着什么?X是什么?
谢谢:-)
发布于 2012-02-03 03:46:44
作为对我全部答案的总结,请考虑以下几点:
template <typename T> void IterateOverContainer(T container) {
/* Error! */
T::iterator itr(container.begin());
}在这里,iterator是嵌套在T中的类型;例如,std::vector<int>::iterator。为了避免这里的歧义,必须使用typename关键字:
template <typename T> void IterateOverContainer(T container) {
/* Now good! */
typename T::iterator itr(container.begin());
}这显然是一个类型的名称(这就是typename的意思!),所以很明显,我们希望声明一个变量,而不是调用一个函数。
尽管如此,使用新的C++11特性,您可以完全避免使用auto。
template <typename T> void IterateOverContainer(T container) {
auto itr(container.begin());
}或者更清楚地说:
template <typename T> void IterateOverContainer(T container) {
auto itr = container.begin();
}现在,关于您的问题:T::x(y)如何声明变量?嗯,由于C的奇怪之处,这是一个完全合法的变量声明:
int (x);就像
int x;所以如果我们有这样的东西
template <typename T> void IterateOverContainer(T container) {
/* Error! */
T::iterator(itr);
}这可以解释为类型为itr的变量T::iterator的声明,也可以解释为对作为参数传递itr的函数T::iterator的调用。typename的使用消除了它是哪一个歧义。
有趣的是,这一额外括号的规定与最令人烦恼的Parse存在的原因相同。我希望你永远不会遇到它。:-)
希望这能有所帮助!
发布于 2012-02-03 04:05:40
如前所述,T::x可以表示在T中定义的x类型(可能是class或typedef),也可能意味着“指向T成员函数x的指针”。
编译器通常有可能根据某些提示(您编写了T::x foo或void (T::*)() foo = T::x?)来判断哪个是正确的( Visual是这样做的,GCC过去也是这样做的(因为,在那个时候,人们可以在GCC上编译代码,而不是在Visual上编译)。该标准要求typename消除困难案例的歧义。
https://stackoverflow.com/questions/9123396
复制相似问题