How can I sort a container based on std::tm?
I need to sort my custom class based on the std struct tm
object. I would like to know if I am approaching this correctly and ask for suggestions for the comparison function. Originally, I was converting each std::tm
member to some base number (like Ticks
in .NET DateTime
), but I thought that might be excessive.
I don't have to use a list
, but I do have to use a Container<MyClass*>
. I would prefer the list
, though. This is my custom class:
class MyClass
{
public:
std::tm _datetime;
stati开发者_JS百科c bool ComparePointers(MyClass*& lhs, MyClass*& rhs);
};
bool MyClass::ComparePointers(MyClass*& lhs, MyClass*& rhs)
{
// ??
}
This is my main function:
int main()
{
std::list<MyClass*> classes;
MyClass* class_1 = new MyClass(); classes.push_back(class_1);
MyClass* class_2 = new MyClass(); classes.push_back(class_2);
MyClass* class_3 = new MyClass(); classes.push_back(class_3);
list.sort(MyClass::ComparePointers);
}
You can use mktime
to convert a std::tm
value to a time_t
which can be compared.
The easiest solution is to convert the std::tm
instance into an integral value, such as seconds since the epoch. Do this for both objects in the ComparePointers
function, then compare the values.
Another more complicated method is to compare each member of the std::tm
, such as year, month, day, minutes, etc.
By the way, the comparison function is misnamed. You are not comparing pointers, but time and date values.
As suggested by @ChristianAmmer, you can use mktime()
to convert tm
to time_t
for comparison. But since C++11, you can also use a lambda expression instead of defining a comparison function:
#include <list>
#include <ctime>
#include <memory>
#include <iostream>
using namespace std;
class MyClass {
public:
// I added a constructor to initialize _datetime just for testing.
MyClass() {
time_t t = time(nullptr);
_datetime = *localtime(&t);
_datetime.tm_sec = rand() % 60;
}
tm _datetime;
};
int main() {
list<unique_ptr<MyClass>> classes;
classes.push_back(unique_ptr<MyClass>(new MyClass));
classes.push_back(unique_ptr<MyClass>(new MyClass));
classes.push_back(unique_ptr<MyClass>(new MyClass));
// C++14: classes.push_back(make_unique<MyClass>());
classes.sort([](unique_ptr<MyClass>& a, unique_ptr<MyClass>& b) {
return mktime(&a->_datetime) < mktime(&b->_datetime);
});
for (auto const &mc : classes)
cout << asctime(&mc->_datetime);
return 0;
}
Output:
Mon Jul 09 11:24:34 2018
Mon Jul 09 11:24:41 2018
Mon Jul 09 11:24:47 2018
Note 1: As an C++11 exercise, I replaced your raw pointers by instances of unique_ptr<>
. This way, your example code no longer leaks the MyClass
pointers on program exit.
Note 2: The function mktime()
might modify the passed tm
struct. If this causes any issues, then you can copy the tm
struct in the lambda expression first.
Note 3: I used the functions localtime()
and asctime()
just for demonstration. Recent Microsoft compilers consider them unsafe and suggest to use localtime_s()
and asctime_s()
instead.
Code on Ideone
精彩评论