过载解决故障

Trouble With Overload Resolution

本文关键字:故障 解决      更新时间:2023-10-16

我想说,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;
};