1

I have a vector of objects:

struct Student{   
  string name;   
  string id;   
  string major;
  int age;
};

vector<Student> s;

Is there any way to write ONE general (maybe template) function to sort this vector (or array) based on different fields instead of writing four different functions?

2
  • 1
    The standard library provides an overload for std::sort which accepts a binary predicate, you could define your own comparison using a lambda/functor. See examples here. Commented Dec 1, 2019 at 22:45
  • 1
    Yes, it's possible. Write a binary comparator predicate type that, based on its internal state, compares different fields. You have to write one at least somewhat anyway, as no one knows how to sort Student objects without one. Just make it flexible to allow specifying which field(s) to sort by. Commented Dec 1, 2019 at 22:46

1 Answer 1

5

I think the previous comments all said that it is possible to write such a comparison function. But if I understand you correctly, you want one function for all 4 comparisons (maybe in a templated way). There is indeed, when using member object pointers (EDIT: was member function pointers, thanks to @WhozCraig for pointing it out):

#include <vector>
#include <algorithm>
#include <iostream>

struct Student {
    std::string name;
    std::string id;
    std::string major;
    int age;
};

template<typename T>
struct Comparator {
    const T Student::* member;

    bool operator()(const Student& stu1, const Student &stu2) const
    {
        return stu1.*member < stu2.*member;
    }

};


int main()
{
    Comparator<int> cint{&Student::age};
    Comparator<std::string> cstring{&Student::name};

    std::vector<Student> vec = {{"Paul", "P", "Mathematics", 42}, {"John", "J", "Computer Science", 43}};

    std::sort(begin(vec), end(vec), cint);
    for(auto &s: vec)
    {
        std::cout << s.age << "\n";
    }

    std::sort(begin(vec), end(vec), cstring);
    for(auto &s: vec)
    {
        std::cout << s.name << "\n";
    }

    return 0;
}

Note that templating wouldn't even be necessary if all your member variables were of the same type. You could also provide an overload for Comparator<int> that default initializes member with &Student::age since there is only one int member, this would reduce the writing effort a bit.

But I think that concerning runtime speed, a lambda in place could be faster.

Sign up to request clarification or add additional context in comments.

1 Comment

"There is indeed, when using member function pointers:" - for the record, those aren't member function pointers; those are member variable pointers. Outside of that, interesting idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.