为什么在依赖类型中,'typedef'后面需要加上'typename'?

8

依赖类型通常需要使用typename告诉编译器该成员是一个类型,而不是函数或变量。

然而,并非总是这样。
例如,基类不需要这样做,因为它只能是一个类型:

template<class T> struct identity { typedef T type; }
template<class T> class Vector : identity<vector<T> >::type { };  // no typename

现在我的问题是,为什么typedef后面有时需要加上typename?关于这个问题,请看下文解答。
template<class T> class Vector
{
    typedef typename /* <-- why do we need this? */ vector<T>::iterator iterator;
};

为什么不问一个关于static的同样的问题呢? - n. m.
1
@n.m.:哦,抱歉我现在明白了。是的,我没有考虑到这一点,尽管我认为这可能是因为默认情况下隐式整型...所以static x;默认会是int类型,不是吗?(或者至少在C语言中是这样的吧?)但说实话,我不确定,这是个好问题。 - user541686
C语言在大约15年前也放弃了隐式int :) - user743382
1个回答

7

typedef不需要出现在类型之前。

template <typename T>
struct S { typedef T type; };
template <typename T>
void f() { typename S<T>::type typedef t; }

这是完全有效的。在这种情况下,如果 typename 是可选的,解析过程会变得复杂。我能理解这一点。
template <typename T>
void f() { typedef S<T>::type t; }
< p >< em > 可能会有不同的解释,但这将引入意想不到的情况,其中 < code > typedef 关键字的位置突然变得重要。< / em >< / p >

1
在这种情况下,也许是因为让它依赖于typedef关键字的位置会更糟糕? - user743382
1
“typedef S<T>::type t;” 这个语句怎么可以有不同的解释?只有在这里 S<T>::type 才能是一种类型,才能使表达式有效。 - bolov
我猜重点在于,由于它位于“typedef”内部,因此只能将其视为类型而非变量进行处理。 - bolov
@bolov,你看到我的回答的第一部分了吗?对于编译器来说,S<T>::type typedef t;会非常复杂,因为首先需要解析S<T>::type,确定它是一个变量,然后当看到typedef时,整个声明需要重新解析。 - user743382
@bolov 当你发表评论的时候,我已经扩展了我的回答并加上了“为了一致性”的原因。 :) - user743382
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接