I have a vector of pointer of a custom object std::vector<MyObject*>
. The object has an index, a number and a timestamp (time of creation of the object). The timestamp is unique, the number can be either -1 (the object is not been assigned a number yet) or a positive value; if the object has a number greater than 0, the number is unique.
class MyObject {private: int id; int number; time_t timestamp;public: MyObject(int id, int number, time_t timestamp) : id(id), number(number), timestamp(timestamp) {}};
I want to order the vector using a custom comparison function: if the two instances of my object have a number, I order using the number (descending), if not I order using the timestamp (descending).
So I added the following to the MyObject
class:
static bool compareByDescendingNumberAndTimestamp(MyObject * a, MyObject * b) { if (a->number > 0 && b->number > 0) { return a->number > b->number; } return a->timestamp > b->timestamp; }
And finally sort the vector:
std::vector<MyObject*> myObjects;auto object1 = new MyObject(1, 24097, 1200);auto object2 = new MyObject(2, 24096, 1100);auto object3 = new MyObject(3, -1, 1000);auto object4 = new MyObject(4, -1, 900);auto object5 = new MyObject(5, 24099, 800);auto object6 = new MyObject(6, 24095, 850);myObjects.push_back(object1);myObjects.push_back(object2);myObjects.push_back(object3);myObjects.push_back(object4);myObjects.push_back(object5);myObjects.push_back(object6);std::sort(myObjects.begin(), myObjects.end(), MyObject::compareByDescendingNumberAndTimestamp);
The order I intended to have is the following:
ID Number Timestamp5 24099 8001 24097 12002 24096 11003 - 10004 - 9006 24095 850
But what I actually got is:
ID Number Timestamp1 24097 12002 24096 11003 - 10004 - 9005 24099 8006 24095 850
After some research I find this page. As far as I understood, my comparison function does not satisfy the requirements of Compare. In particular the comp(a, b)
does not establish a strict weak ordering relation.
Is there a way I can write a comparison function to order my vector as I want?
Note: I've been using c++17.
Edit:
Minimal reproducible example (notice that the initail order of the vector influences the end result):
#include <iostream>#include <vector>#include <algorithm>#include <string>class MyObject {public: int id; int number; time_t timestamp; MyObject(int id, int number, time_t timestamp) : id(id), number(number), timestamp(timestamp) {} static bool compareByDescendingNumberAndTimestamp(MyObject * a, MyObject * b) { if (a->number > 0 && b->number > 0) { return a->number > b->number; } return a->timestamp > b->timestamp; }};int main() { std::vector<MyObject*> myObjects; auto object1 = new MyObject(1, 24097, 1200); auto object2 = new MyObject(2, 24096, 1100); auto object3 = new MyObject(3, -1, 1000); auto object4 = new MyObject(4, -1, 900); auto object5 = new MyObject(5, 24099, 800); auto object6 = new MyObject(6, 24095, 850); myObjects.push_back(object6); myObjects.push_back(object5); myObjects.push_back(object4); myObjects.push_back(object3); myObjects.push_back(object2); myObjects.push_back(object1); std::sort(myObjects.begin(), myObjects.end(), MyObject::compareByDescendingNumberAndTimestamp); std::cout << "ID\tNumber\tTimestamp" << std::endl; for (auto const & object: myObjects) { std::cout << std::to_string(object->id) << "\t" << std::to_string(object->number) << "\t"<< std::to_string(object->timestamp) << std::endl; } return 0;}