非成员运算符<(),用于模板类的嵌套类与编译器不匹配

时间:2011-10-27 15:39:39

标签: c++ templates operator-overloading

我遇到了模板化比较运算符的问题,用于比较依赖于模板参数的类型的实例。我已经在试管了一段时间,包括SO,并努力去理解我做错了什么。我认为这是依赖名称查找的问题,但这并没有帮助我使代码工作: - (

这是一个最小的测试用例:

template<typename T>
struct Foo
{
  struct Bar {
     T t;
  };

  Bar b;
};


template<typename T>
inline bool operator<(const typename Foo<T>::Bar& b1, const typename Foo<T>::Bar& b2)
{ return b1.t < b2.t; }


int main()
{
  Foo<int> f1, f2;
  return (f1.b < f2.b?  0 : 1);
}

编译给出:

templated-comparison-op.cpp: In function ‘int main()’:
templated-comparison-op.cpp:20:20: error: no match for ‘operator<’ in ‘f1.Foo<int>::b < f2.Foo<int>::b’
templated-comparison-op.cpp:20:20: note: candidate is:
templated-comparison-op.cpp:13:13: note: template<class T> bool operator<(const typename Foo<T>::Bar&, const typename Foo<T>::Bar&)

现在我已经将比较运算符作为模板类的成员,它工作正常,所以没有紧迫感。我想了解我在这里缺少的东西;谁能开导我?

编辑:这实际上并不是一个准确的测试用例;在我从中提取这个案例的实际代码中,模板类Foo嵌套在另一个类中,这就是为什么'typename'关键字是必需的。如下面的答案所述,在上面的代码'typename'是不必要的。

编辑:我已经用一个突出显示当前问题的新测试用例替换了原始测试用例,并且还更新了问题标题,因为我正在努力复制我在真实中遇到的确切错误代码库。如果在测试用例中有一个问题的解决方法,那么可能会在实际代码中获得与编译更接近的等价物,因此仍然有兴趣追求这一点。

3 个答案:

答案 0 :(得分:3)

您在函数声明中不需要typename,因为Foo<T>不是依赖类型:

template<typename T>
bool operator<(const Foo<T>& f1, const Foo<T>& f2)
{ return f1.t < f2.t; }

(我不确定他们为什么会产生这个特定的错误,但删除它们会修复它。)

答案 1 :(得分:3)

问题是你的operator<不可用,因为编译器无法自动找出T是什么。

您可以通过声明非模板operator<

来解决您的问题
template<typename T>
struct Foo
{
  struct Bar {
     T t;
  };

  Bar b;

  friend bool operator<(const Bar& b1, const Bar& b2)
  { return b1.t < b2.t; }
};

然后,对operator<表达式operator<的参数相关查找找到x < y声明。

或者,您可以将operator<定义放在定义Bar中(但在这种情况下这并不重要,因为Foo<T>Foo<T>::Bar的关联类)。

答案 2 :(得分:2)

不知道问题是否存在,但参数列表中的typename不应该存在。 (如果表示问题,这是一个可怕的错误消息。)