我想为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容器?
答案 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;
}