运算符的多重重载

Multiple Overloading of Operators

正如您从代码中看到的那样,我想重载 < 运算符两次。 1 按 dist 排序,另一个按 nodeID 排序。我想检查是否有任何方法可以调用不同的重载方法。例如在 compLoc 方法中,当我使用 sort() 方法时,我希望它按 nodeID 排序,但在其他方法中我希望它按 dist.

排序
struct AttSet{
int nodeID;
double dist;

bool operator < (const AttSet & str) const{
    return (dist < str.dist);
}
/*
bool operator <(const AttSet & str){
    return (nodeID < str.nodeID);
*/
bool operator == (const AttSet & str){
    return nodeID == str.nodeID;
}};

void compLoc(Edge *edge, vector<Node*> &vertices){
int l = edge->length;
int vl = edge->head->nodeID;
int vr = edge->tail->nodeID;
/*
sort(vertices[vl]->attSet.begin(), vertices[vl]->attSet.end());
sort(vertices[vr]->attSet.begin(), vertices[vr]->attSet.end());
vector<AttSet> vInterSec;
set_intersection(vertices[vl]->attSet.begin(), vertices[vl]->attSet.end(), vertices[vr]->attSet.begin(), vertices[vr]->attSet.end(), back_inserter(vInterSec));
*/}

你不能那样做,因为编译器看不出两者之间的区别:

bool operator < (const AttSet & str) const; //this const doesn't allow to override any property of object(instance of AttSet) if I remember

bool operator < (const AttSet & str);

有相同的 return 类型,相同的参数(相同的签名)

编译器无法选择哪个更好

不能有具有相同签名的重载。这适用于任何功能。您将如何决定使用哪个版本?

如果您想根据不同的标准对对象进行排序,您应该使用将自定义比较器函数作为第三个参数的 sort 版本。

编辑: 当然你需要提供比较器。如果您有这样的能力,我建议将比较器作为 class 的静态函数提供。这样你就不会污染封闭的命名空间,你可以在不暴露任何 getter 的情况下访问 class 的私有。由于您的属性是 public lambda 就足够了,并且可能是 best/cleanest 方法。

喜欢冒险我做了一个简单的c++11练习程序。对于它的价值,如果您决定进行适当的封装,我已经展示了两种方法:

#include <iostream>
#include <algorithm>
#include <vector>
#include <initializer_list>
#include <cassert>
using namespace std;

template<typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& v){
    for(const auto& el : v){
        out << el << '\n';
    }
    return out;
}

class A {
    int a;
    int b;
public:
    A(std::initializer_list<int> l){
        assert(l.size() == 2);
        auto i = l.begin();
        a = *i;
        ++i;
        b = *i;
    }

    friend std::ostream& operator<<(std::ostream& stream, const A& e){
        return stream << e.a << ' ' << e.b;
    }

    static bool compareViaA(const A& lhs, const A& rhs){
        return rhs.a > lhs.a;
    }

    static bool compareViaB(const A& lhs, const A& rhs){
        return rhs.b > lhs.b;
    }
};

int main() {
    std::vector<A> v {{2,3}, {3,2}, {1,4}, {4,1}};
    //sort(v.begin(), v.end(), [](const A& a, const A& b){return a.a > b.a;}) // fails because of privacy violation
    sort(v.begin(), v.end(), A::compareViaA);
    std::cout << v << '\n';
    sort(v.begin(), v.end(), A::compareViaB);
    std::cout << v << '\n';
    return 0;
}

直播:http://ideone.com/lDMujx.

你不能那样做。他们的签名完全一样。

使用仿函数或 lambda 并将其传递给您想要的任何算法。

std::sort(std::begin(container), std::end(container),
    [](const element_type& lhs, const element_type& rhs) { return ...; });

另一种方法:

struct compare_by_node_id {
    bool operator()(const AttSet& lhs, const AttSet& rhs) const {
        return lhs.nodeID < rhs.nodeID;
    }
};

struct compare_by_dist {
    bool operator()(const AttSet& lhs, const AttSet& rhs) const {
        return lhs.dist < rhs.dist;
    }
};

您可以将其传递给算法,例如:

std::sort(std::begin(container), std::end(container), compare_by_node_id());

据我所知,没有很好的方法可以做到这一点,因为编译器会将它们视为完全相同的,并会抛出错误。如果您需要这样做,请使用 < 运算符作为最常出现的任何内容,然后编写一个您可以调用的方法来比较两个对象。像这样:

bool operator< (const Blah &blah) const {
    return (most often operation)
}

bool Blah::other_operation(const Blah &blah) const {
    return (other operation)
}

我认为你可以通过使用仿函数并将比较器(运算符<重载)放在 AttSet 之外来实现它。 这是一个简单的例子:

struct AtrComparator {
     bool distcmp;
     AttrComparator(bool distcmp): distcmp(distcmp) {}
     bool operator() (const AttSet &s1, const AttSet &s2) {
          if(distcmp) {
               return s1.dist < s2.dist;
          } else {
               return s1.nodeID < s2.nodeID;
          }
     }
}

然后您可以通过不同的提要、dist 或nodeID 进行排序。 .例如:

sort(vertices[vl]->attSet.begin(), vertices[vl]->attSet.end(), AttComparator(true));
sort(vertices[vl]->attSet.begin(), vertices[vl]->attSet.end(), AttComparator(false));