xcr*_*ypt 17 c++ templates typename
class A
{
static int iterator;
class iterator
{
[...]
};
[...]
};
Run Code Online (Sandbox Code Playgroud)
我(我想)理解为什么typename需要这里:
template <class T>
void foo() {
typename T::iterator* iter;
[...]
}
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么typename不需要这里:
void foo() {
A::iterator* iter;
[...]
}
Run Code Online (Sandbox Code Playgroud)
谁能解释一下?
编译器之所以没有后者的问题,我发现在评论中得到了很好的回答:
在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种不同类型将具有不同的含义,这是不可接受的."
Ker*_* SB 41
C++中的名称可以涉及三个不同的实体层:值,类型和模板.
struct Foo
{
typedef int A;
static double B;
template <typename T> struct C;
};
Run Code Online (Sandbox Code Playgroud)
这三个名字Foo::A,Foo::B并且Foo::C是三个不同层次的例子.
在上面的例子中,Foo是一个完整的类型,因此编译器已经知道Foo::A等等.但现在想象一下:
template <typename T> struct Bar
{
T::A x;
};
Run Code Online (Sandbox Code Playgroud)
现在我们遇到麻烦了:是什么T::A?如果T = Foo,那么T::A = int,哪种类型,一切都很好.但是什么时候T = struct { char A; };,这T::A是一个没有意义的价值.
因此,编译器的需求是你告诉它T::A,并T::B和T::C被认为是.如果你什么都不说,那就假定它是一个值.如果你说typename,它是一个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);
}
};
Run Code Online (Sandbox Code Playgroud)
二次检查,如是否T::B可以转换为int,是否a和x可以成倍增加,以及是否C<int>真的有成员函数gobble都推迟,直到你真正实例化的模板.但是,名称表示值,类型或模板的规范是代码语法正确性的基础,必须在模板定义期间提供.