为什么关键字"typename"在限定的从属名称之前需要,而不是在限定的独立名称之前?
Why is the keyword "typename" needed before qualified dependent names, and not before qualified independent names?
class A
{
static int iterator;
class iterator
{
[...]
};
[...]
};
我(想我)理解这里需要typename
的原因:
template <class T>
void foo() {
typename T::iterator* iter;
[...]
}
但是我不明白为什么这里不需要typename
:
void foo() {
A::iterator* iter;
[...]
}
谁能解释一下?
编辑:
编译器对后者没有问题的原因,我发现在注释中回答得很好:
在A::iterator
的情况下,我不明白为什么编译器不会将其与static int iterator
混淆?——xcrypt
@xcrypt因为它知道A::iterator
是什么,并且可以根据使用方式选择哪一个- Seth Carnegie
编译器在限定依赖名之前需要typename
的原因,在我看来,Kerrek SB在接受的答案中回答得很好。一定要阅读对该答案的评论,特别是iammilind:
"T::A * x;,当T::A是类型且T::A是值时,此表达式可以为真。如果A是一个类型,那么它将导致指针声明;如果A是一个值,那么它将导致乘法。因此,一个模板对于2个不同的类型会有不同的含义,这是不可接受的。"
c++中的名称可以属于三个不同的实体层:类型、值和模板。
struct Foo
{
typedef int A; // type
static double B; // value
template <typename T> struct C; // template
};
三个名称Foo::A
, Foo::B
和Foo::C
是所有三个不同层的例子。
在上面的例子中,Foo
是一个完整的类型,所以编译器已经知道Foo::A
等指的是什么。但是现在想象一下:
template <typename T> struct Bar
{
T::A x;
};
现在我们有麻烦了:T::A
是什么?如果是T = Foo
,则是T::A = int
,这是一个类型,一切正常。但是当T = struct { static char A; };
时,则T::A
是值,这没有意义。
T::A
、T::B
和T::C
是什么假定是什么。如果你什么都没说,它就被认为是一个值。如果输入typename
,它是一个类型名,如果输入template
,它是一个模板:
template <typename T> struct Bar
{
typename T::A x; // ah, good, decreed typename
void foo()
{
int a = T::B; // assumed value, OK
T::template C<int> z; // decreed template
z.gobble(a * x);
}
};
次要检查,如T::B
是否可转换为int
, a
和x
是否可以相乘,以及C<int>
是否真的有一个成员函数gobble
,这些都被推迟到您实际实例化模板时。但是,名称是否表示值、类型或模板的规范是代码语法正确性的基础,必须在模板定义期间提供。
因为在非模板foo中,您正在执行有效的乘法操作(假设您在该操作之前声明了iter
)。如果尝试省略星号,就会出现编译错误。int隐藏了类。
typename关键字而不是阻止隐藏。只有gcc不正确地实现了它。因此,如果您尝试用A
作为类型实例化您的函数模板,那么将得到编译错误,因为在typenake 之后指定的名称将在任何符合标准的编译器上引用非类型。
因为编译器在模板实例化之前不知道T::iterator
是什么,所以它不知道iterator
是一个类变量、类型、函数还是什么。您需要通过使用typename
来告诉它它是一个类型。
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- C++中的"inline"关键字
- 如何确保C++函数在定义之前声明(如override关键字)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 独立读取-修改-写入顺序
- 谷歌模拟和覆盖关键字
- 带有多个独立参数的C++For循环
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 为什么"delete"关键字不删除节点?
- 在 c++ 中正确定义"this"关键字?
- 这个额外的关键字在这个 c++ 类声明中是什么意思?
- 在 typedef 内部使用 const 关键字和在 typedef 外部使用 const 关键字之间有区别吗?
- C++ - 为什么这里需要'template'关键字?
- C++函数的关键字?
- 使用 'typename' 关键字将非类型视为依赖上下文中的类型
- "friend"关键字在C++中是什么意思?
- 声明C++数组(带或不带 "new" 关键字)
- 为什么关键字"typename"在限定的从属名称之前需要,而不是在限定的独立名称之前?