运算符的多重重载
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;
}
你不能那样做。他们的签名完全一样。
使用仿函数或 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));
正如您从代码中看到的那样,我想重载 < 运算符两次。 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;
}
你不能那样做。他们的签名完全一样。
使用仿函数或 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));