运算符覆盖排序并不是我想要的

时间:2022-06-01 17:47:54

I am trying to sort a person vector by person.name and age. Therefore, I tried to override the operator< in the Person definition, and to use functor with std::sort().

我试图按person.name和年龄排序一个人矢量。因此,我试图在Person定义中覆盖operator <,并使用带有std :: sort()的functor。

However, I did not get what I want. My expectation is that Persons are first ordered by their name, and then by their age. But I get the same result with both solutions:

但是,我没有得到我想要的东西。我的期望是,人们首先按他们的名字排序,然后按他们的年龄排序。但是我得到了两个解决方案相同的结果:

che is less than xu
(wu, 30)
(che, 34)
(xu, 21)

What I expect order is:

我期望的订单是:

(che, 34)
(wu, 30)
(xu, 21)

Could anyone help point the mistake I made? Thanks

任何人都可以指出我犯的错误吗?谢谢

The source code is:

源代码是:

class Person{
 public:
  string _name;
  int _age;

 public:
  Person(string name, int age):_name(name),_age(age){
  }
    bool operator<(const Person* b) const {
   cout<<"Expect "<<_name <<b->_name <<"   "<< (_name < b->_name)<<endl;
  if(_name != b->_name) {
      return _name < b->_name;
   }
    else return _age<b->_age;
   }

   bool operator<(const Person& b) const {
     if(_name!=b._name) {
       cout<<_name <<" is less than "<<b._name<<endl;
       return _name<b._name;
     }  else return _age<b._age;
   }
  friend ostream& operator<<(ostream& out, const Person& b) {
    out << "(" << b._name << ", " << b._age << ")"<<endl;
    return out;
}

};

bool PersonCompare(const Person* a, const Person* b ){
     cout<<"Expect "<<a->_name <<b->_name <<"   "<< (a->_name < b->_name)<<endl;
    if(a->_name != b->_name) {
      return a->_name < b->_name;
    }
    else return a->_age<b->_age;
}

class PersonPrint{
 public:
  PersonPrint(){
  }

  void operator()(const Person& person){
    cout<<person;
  }
 void operator()(const Person* person){
    cout<<*person;
  }
};




void testSort(){
  vector<Person*> personsList;
  personsList.push_back(new Person("xu", 12));
  personsList.push_back(new Person("che", 23));
  personsList.push_back(new Person("sxy", 34));
  /*std::sort(personsList.begin(), personsList.end(), [](Person* a, Person* b ){
      if(a->_name!=b->_name) return a->_name<b->_name;
      else return a->_age<b->_age;
      }); *///This works
 /* std::sort(personsList.begin(), personsList.end(), PersonCompare ) *///This works..
  std::sort(personsList.begin(), personsList.end()); //This does not work

  for_each(personsList.begin(), personsList.end(), PersonPrint());
}

============== It is the logic error inside of lambda/operator. After changing if(a._name<b._name) to if(a._name!=b._name), the error is fixed.

==============这是lambda / operator里面的逻辑错误。将if(a._name )更改为if(a._name!=>

/////////////////////////////////////

I updated the code. Add bool operator<(const Person* b) const{} for class Person, and then try to sort a vector of Person*. But the result is not sorted as I expected, and the newly added operator<(const Person*) is not called. Any suggestion here? Thanks

我更新了代码。为类Person添加bool运算符<(const Person * b)const {},然后尝试对Person *的向量进行排序。但是结果没有像我预期的那样排序,并且没有调用新添加的运算符<(const Person *)。这里有什么建议吗?谢谢

1 个解决方案

#1


0  

Your comparison function is treading the territories of undefined behavior. No surprise you are not seeing what you expect. From std::sort's documentation

您的比较函数正在踩踏未定义行为的区域。毫不奇怪,你没有看到你的期望。来自std :: sort的文档

comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

comp - 比较函数对象(即满足Compare要求的对象),如果第一个参数小于(即在之前排序)第二个参数,则返回true。

Requirements of Compare:

比较要求:

The return value of the function call operation applied to an object of type Compare, when contextually converted to bool, yields true if the first argument of the call appears before the second in the strict weak ordering relation induced by this Compare type, and false otherwise.

当上下文转换为bool时,应用于Compare类型的对象的函数调用操作的返回值,如果调用的第一个参数出现在此Compare类型引发的严格弱排序关系中的第二个参数之前,则返回true,否则返回false 。

Your comparison function doesn't meet the criteria of strict week ordering.

您的比较功能不符合严格的周订购标准。

You can simply do:

你可以简单地做:

std::sort(persons.begin(), persons.end(), 
[](const Person& a, const Person& b) { return std::tie(a.name, a.age) < std::tie(b.name, b.age); })

I have written an article on this: https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl which you may want to refer.

我写过一篇文章:https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl您可能想要参考。

Edit(Based on OP's edit):

编辑(基于OP的编辑):

This doesn't works because you have provided member functions for Person class whereas the type on which you want to call is Person*. Both are different types. You will have to move the PrintPerson function's definition outside the class and make it declare as a friend method in Person class. Unfortunately you cannot do the same with the bool operator<(Person *a, Person *b) because operator overloading doesn't works with pointer types. Your only alternative is to pass a comparer.

这不起作用,因为您为Person类提供了成员函数,而您要调用的类型是Person *。两者都是不同的类型。您必须在类之外移动PrintPerson函数的定义,并将其声明为Person类中的friend方法。不幸的是你不能对bool运算符<(Person * a,Person * b)做同样的事情,因为运算符重载不适用于指针类型。您唯一的选择是通过比较器。

#1


0  

Your comparison function is treading the territories of undefined behavior. No surprise you are not seeing what you expect. From std::sort's documentation

您的比较函数正在踩踏未定义行为的区域。毫不奇怪,你没有看到你的期望。来自std :: sort的文档

comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

comp - 比较函数对象(即满足Compare要求的对象),如果第一个参数小于(即在之前排序)第二个参数,则返回true。

Requirements of Compare:

比较要求:

The return value of the function call operation applied to an object of type Compare, when contextually converted to bool, yields true if the first argument of the call appears before the second in the strict weak ordering relation induced by this Compare type, and false otherwise.

当上下文转换为bool时,应用于Compare类型的对象的函数调用操作的返回值,如果调用的第一个参数出现在此Compare类型引发的严格弱排序关系中的第二个参数之前,则返回true,否则返回false 。

Your comparison function doesn't meet the criteria of strict week ordering.

您的比较功能不符合严格的周订购标准。

You can simply do:

你可以简单地做:

std::sort(persons.begin(), persons.end(), 
[](const Person& a, const Person& b) { return std::tie(a.name, a.age) < std::tie(b.name, b.age); })

I have written an article on this: https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl which you may want to refer.

我写过一篇文章:https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl您可能想要参考。

Edit(Based on OP's edit):

编辑(基于OP的编辑):

This doesn't works because you have provided member functions for Person class whereas the type on which you want to call is Person*. Both are different types. You will have to move the PrintPerson function's definition outside the class and make it declare as a friend method in Person class. Unfortunately you cannot do the same with the bool operator<(Person *a, Person *b) because operator overloading doesn't works with pointer types. Your only alternative is to pass a comparer.

这不起作用,因为您为Person类提供了成员函数,而您要调用的类型是Person *。两者都是不同的类型。您必须在类之外移动PrintPerson函数的定义,并将其声明为Person类中的friend方法。不幸的是你不能对bool运算符<(Person * a,Person * b)做同样的事情,因为运算符重载不适用于指针类型。您唯一的选择是通过比较器。