我想说在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"
问题
问题是当我调用operator&lt;像这样:
Example<vector<int>::iterator> ex1(**foo**);
Example<vector<int>::iterator> ex2(**bar**);
ex1<ex2;
它调用A :: operator&lt;很好,但它递归地称自己做ex1.start<ex2.start
而不是查找更专业的运算符&lt; for vector :: iterator。导致错误C2039:start不是vector :: iterator的成员。
有没有人建议确保A :: operator&lt;调用正确的运算符&lt;对于ex1.start?
注意:大约有20个类使用A :: operator&lt;所以,如果我可以避免在每个类别中单独定义它,那将是非常棒的。
答案 0 :(得分:2)
我的谦虚建议:不要这样做。
除了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;
};