std :: set有多个排序选项

时间:2015-11-29 00:43:01

标签: c++

我想为c ++ std :: set容器提供多个排序选项。 我试图创建一个自定义比较器,引用私有类成员(sortingMethod)来决定如何排序:

class StudentBook{
    int sortingMethod; //0-BY_ID, 1-BY_AGE, 2-BY_GPA, etc...
    struct studentComparator {
        bool operator()(Student* a, Student* b)
        {
            switch (sortingMethod) {
            case 1:
                return a->getId() >= b->getId();
                break;
            case 2:
                return a->getAge() >= b->getAge();
                break;
            case 3:
                return a->getGPA() >= b->getGPA();
                break;
            default:
                return true;
                break;
        }
    };
    std::set<Student*, studentComparator> students;

}

此代码无法编译。错误:

  

“从这个位置”,“无效使用非静态数据成员'StudentBook :: sortingMethod'”

我想使用一个集,因为它没有重复属性。 有没有正确的方法,或者我应该切换到另一个STL容器?

1 个答案:

答案 0 :(得分:2)

代码中的问题是您尝试引用sortingMethod类中的studentComparator。你不能这样做,因为studentComparator是一个独立的类,除非你将外部实例的指针/引用传递给内部实例,否则无法访问封闭类的成员变量(我认为这是其中之一)许多)C ++和Java之间的差异)。将sortingMethod封装在studentComparator内并通过其构造函数传递。

这个想法是构造一个比较器函子,它以你想要排序的方式作为构造函数参数。换句话说,比较器仿函数具有状态。在构建std::set时,您需要明确pass the comparator to its constructor。 下面是一个如何操作的简单示例,使用2状态布尔比较器,您可以进一步概括:

#include <iostream>
#include <set>
#include <string>

struct Foo
{
    int age_;
    std::string name_;
    friend std::ostream& operator<<(std::ostream& os, const Foo& rhs)
    {
        return os << rhs.age_ << " " << rhs.name_;
    }
    struct Compare // custom comparator
    {
        bool by_name_; // compare by age
        Compare(bool by_name = false): by_name_(by_name) {}
        bool operator()(const Foo& lhs, const Foo& rhs)
        {
            return by_name_ ? (lhs.name_ < rhs.name_) : (lhs.age_ < rhs.age_);
        }
    };
};

int main()
{
    Foo x{1, "Silver"}, y{2, "John"}, z{3, "Long"};

    std::set<Foo, Foo::Compare> by_name(Foo::Compare{true}); // sort by name
    by_name.insert(x);
    by_name.insert(y);
    by_name.insert(z);

    std::set<Foo, Foo::Compare> by_age(Foo::Compare{false}); // sort by age
    by_age.insert(x);
    by_age.insert(y);
    by_age.insert(z);

    std::cout << "By name:" << std::endl;
    for (auto && elem : by_name)
        std::cout << elem << std::endl;
    std::cout << "By age:" << std::endl;
    for (auto && elem : by_age)
        std::cout << elem << std::endl;
}

Live on Coliru