过载分辨率问题

时间:2012-08-25 17:31:24

标签: c++ operator-overloading overload-resolution

我想说在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;所以,如果我可以避免在每个类别中单独定义它,那将是非常棒的。

1 个答案:

答案 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;
};