我想说,SO上已经有很多C++重载问题,但在看了一个小时以及论坛和新闻组上的其他帖子后,我仍然被难住了。
背景
我创建了一个名称空间,称之为a,其中一堆类具有相同的方式来实现<操作人员为了避免代码重复,我写了这样的:
namespace A{
template<typename T>
bool operator< (const T&, const T&);
}
在一个名为operator_forwards.h的头文件中,以及其他一些声明。然后,我添加了这样一行:,使其成为正确类的朋友
//example.h
#include "operator_forwards.h"
namespace A{
template<typename T>
class Example{
public:
friend bool operator< <>(const Example<T>&, const Example T&);
private:
T start;
};
}
最后,我把定义放在一个名为operators.h的文件中,如下所示:
namespace A{
template<typename T>
bool operator<(const T& lhs, const T& rhs){
using std::operator<;
return lhs.start<rhs.start;
}
}
并将所有内容都包含在一个头文件中:
//A.h
#include "example.h"
#include "operators.h"
问题
问题是当我打电话给接线员<像这样:
Example<vector<int>::iterator> ex1(**foo**);
Example<vector<int>::iterator> ex2(**bar**);
ex1<ex2;
它调用A::运算符<很好,但是它递归地调用自己来执行ex1.start<ex2.start
,而不是查找更专业的运算符<对于vector::迭代器。导致错误C2039:start不是向量::迭代器的成员。
有人对确保A::operator<调用正确的运算符<例如1开始?
注意:大约有20个类使用A::运算符<所以如果我能避免在每个类中单独定义它,那就太棒了。
我的建议是:不要那样做。
与A::operator<
的实现相比,您将不得不在更多的地方处理这个问题。A
中任何位置的任何代码都可能被这个意外的模板所欺骗,该模板声称对任何内容都支持operator<
,但实际上只能在具有start
成员的类型上执行。
在您的案例中,您将在任何位置的每个相关类中放置一个friend
声明。在这些类中简单地实现它几乎不需要更多的代码。如果这冒犯了你的代码复制敏感性,那么考虑一个共享基类:
template <typename T>
class IterWrapper {
public:
IterWrapper() {}
explicit IterWrapper(T it) : start(it) {}
bool operator< (const IterWrapper<T>& rhs) { return start < rhs.start; }
protected:
T start;
};