4

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

#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;
}

当我有 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

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

4

3 回答 3

13

你错过了一个typename

typename map<A,B>::const_iterator x = D.find(a);

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

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

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

在模板声明或定义中使用并且依赖于模板参数的名称被假定为不命名类型,除非适用的名称查找找到类型名称或该名称由关键字 typename 限定。

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

于 2013-08-09T21:02:46.090 回答
2

您错过了关键字typename,它在引用类型并取决于模板参数的限定名称之前是必需的:

typename map<A,B>::const_iterator x = D.find(a);
于 2013-08-09T21:04:46.190 回答
1

您必须添加typename

typename map<A,B>::const_iterator x = D.find(a);

解释:
typename声明后面的名称应该被视为一种类型。否则,名称将被解释为引用非类型。

于 2013-08-09T21:03:44.237 回答