Сортировать с переопределением оператора не получается я хочу

Я пытаюсь отсортировать человека вектор по person.name и возрасту. Поэтому я попытался переопределить operator< в Person определение, и использовать функтор с std::sort(),

Однако я не получил то, что хочу. Я ожидаю, что люди сначала упорядочены по имени, а затем по возрасту. Но я получаю одинаковый результат с обоими решениями:

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

Я ожидаю, что заказ:

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

Может ли кто-нибудь помочь указать на ошибку, которую я сделал? Спасибо

Исходный код:

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());
}

============== Это логическая ошибка внутри лямбда / оператора. После изменения if(a._name<b._name) в if(a._name!=b._name), ошибка исправлена.

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

Я обновил код. добавлять bool operator<(const Person* b) const{} для класса Person, а затем попробуйте отсортировать вектор Person*, Но результат не отсортирован, как я ожидал, а недавно добавленный operator<(const Person*) не называется. Любое предложение здесь? Спасибо

1 ответ

Решение

Ваша функция сравнения состоит в неопределенном поведении. Не удивительно, что вы не видите того, что ожидаете. Из документации std::sort

comp - объект функции сравнения (т. е. объект, который удовлетворяет требованиям Compare), который возвращает true, если первый аргумент меньше (т.е. упорядочен раньше) второго.

Требования сравнения:

Возвращаемое значение операции вызова функции, примененной к объекту типа Compare, когда контекстно преобразуется в bool, возвращает true, если первый аргумент вызова появляется перед вторым в строгом слабом порядке упорядочения, вызванном этим типом Compare, и false в противном случае,

Ваша функция сравнения не соответствует критериям строгого недельного заказа.

Вы можете просто сделать:

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); })

Я написал статью об этом: https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl которую вы можете сослаться.

Изменить (на основе редактирования ОП):

Это не работает, потому что вы предоставили функции-члены для Person класс, тогда как тип, который вы хотите вызвать Person*, Оба разных типа. Вам придется переместить PrintPerson определите функцию вне класса и сделайте так, чтобы она объявлялась как метод друга в классе Person. К сожалению, вы не можете сделать то же самое с bool operator<(Person *a, Person *b) потому что перегрузка оператора не работает с типами указателей. Ваша единственная альтернатива - пройти сравнение.

Другие вопросы по тегам