开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜