我在Wiki上查找了关键字typename(http://en.wikipedia.org/wiki/Typename),并给出了一个示例,在T :: bar
之前需要哪个typenametemplate <typename T>
void foo(const T& t)
{
// declares a pointer to an object of type T::bar
T::bar * p;
}
struct StructWithBarAsType {
typedef int bar;
};
int main() {
StructWithBarAsType x;
foo(x);
}
为什么C ++不检查StructWithBarAsType并且在为foo(x)生成代码时发现T :: bar实际上是一个类型?是不可能还是只是效率考虑?
答案 0 :(得分:1)
它假定T::bar
是静态成员,除非事先指定typename
。没有技术限制可以防止编译器在实例化过程中弄清楚T::bar
是否是一种类型,但是为了使编译器实现者更容易一些,做出了决定。它可以产生比人们想象的更大的差异,考虑
T::bar<a,b>c;
这是c
类型的变量T::bar<a,b>
,还是小于,逗号,大于? T::bar < a
后跟b > c
? C ++模板语法有很多不足之处。
答案 1 :(得分:1)
在解析模板时,可能无法确定是否需要类型或值。一个例子是
int v = 2;
template <typename T>
void f() {
T::value * v;
}
此代码可以声明指针或暗示操作。两种解释都不是特别有用。当要求编译器理解该代码时,它不知道类型T
。现在,您可以说:为两种解释做好准备! ......但是如果接下来的行继续进行类似的事情,你手头就会发生组合爆炸。
我可以想象编译器在大多数情况下可以正确地确定其含义。然而,没有进一步的背景,有时是不可能的。在引入typename
时,我也认为需要经常出现这种情况。在某种程度上,auto
和decltype(...)
解决了这一问题,从而摆脱了嵌套类型的许多需求。