我遇到了模板化比较运算符的问题,用于比较依赖于模板参数的类型的实例。我已经在试管了一段时间,包括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'是不必要的。
编辑:我已经用一个突出显示当前问题的新测试用例替换了原始测试用例,并且还更新了问题标题,因为我正在努力复制我在真实中遇到的确切错误代码库。如果在测试用例中有一个问题的解决方法,那么可能会在实际代码中获得与编译更接近的等价物,因此仍然有兴趣追求这一点。
答案 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
不应该存在。 (如果表示问题,这是一个可怕的错误消息。)