C++:"期待;" 在模板中的声明

Vic*_*ler 3 c++ templates

我在模板化类的成员函数中遇到了以下问题:

#include <map>
using std::map;
template <typename A,typename B>
class C {
  public:
    B f(const A&,const B&) const;
  private:
    map<A,B> D;
};
template <typename A,typename B>
B C<A,B>::f(const A&a,const B&b) const {
   map<A,B>::const_iterator x = D.find(a);
   if(x == D.end())
     return b;
   else
     return x->second;
}
Run Code Online (Sandbox Code Playgroud)

当我有g ++编译时,我收到以下错误:

Bug.C: In member function 'B C<A,B>::f(const A&, const B&) const':
Bug.C:12: error:expected ';' before 'x'
Bug.C:13: error: 'x' was not declared in this scope
Run Code Online (Sandbox Code Playgroud)

但是,当我创建类和函数的非模板化版本时,A和B都是int,它编译没有问题.这个错误有点神秘,因为我无法想象为什么它想要一个';' 在'x'之前.

Jes*_*ood 12

你错过了一个typename:

typename map<A,B>::const_iterator x = D.find(a);
Run Code Online (Sandbox Code Playgroud)

请阅读"我在哪里以及为什么要放置"模板"和"typename"关键字?.你typename在这里需要的原因是因为AB模板参数意味着它的含义::const_iterator 取决于什么AB是什么.虽然对于人const_iterator来说,这个名称很明显这是一个迭代器类型,但对于编译器来说,它不知道这是一个类型,数据成员等.

在实例化模板之前,编译器将对第一遍进行语法检查,并通过添加typename让编译器知道将其解析map<A,B>::const_iterator为类型.

此外,C++中有一个特殊规则(从链接问题中可耻地窃取):

假定模板声明或定义中使用的名称以及依赖于模板参数的名称不会命名类型,除非适用的名称查找找到类型名称或名称由关键字typename限定.

如果不添加typename,编译器必须假定它不是类型.