如何为集合 C++ 建立比较器

How do I establish a comparator for a set c++

我有一套,对于这套,我需要两个不同的比较器。例如,对于集合 frontier 我需要按成本排序,但我有另一个集合 board 需要按坐标排序。我知道你 可以 使用比较器作为第二个参数为每个集合定义一个比较器,但我已经试过了,它给了我一个错误。

我尝试使用的代码:

struct tile {
int id;
int xCord;
int yCord;
int cost;

...

bool operator<(const tile& Rhs) const {

    if (cost < Rhs.cost) {
        return true;
    }
    else if (cost < Rhs.cost) {
        return false;
    }
    else {
        if (id < Rhs.id) {
            return true;
        }
        else
            return false;
    }


}

...


};

我用于比较器的另一个结构(我知道这很可能是不正确的,这就是我寻求帮助的原因。):

struct costComp {
int id;
int xCord;
int yCord;
int cost;

costComp() {}

costComp(int a, int b, int c, int d = 0) :
    id(a),
    xCord(b),
    yCord(c),
    cost(d) {}


bool operator<( const tile& Rhs) const {
    if (xCord < Rhs.xCord)
        return true;
    else if (xCord < Rhs.xCord)
        return false;
    else {
        if (yCord < Rhs.yCord)
            return true;
        else if (yCord < Rhs.yCord)
            return false;
        else
            return false;
    }
}
};

然后,我将集合定义为:

set<tile,costComp> startBoard;

我得到的错误:

c2064: term does not evaluate to a function taking 2 arguments

非常感谢任何帮助。

std::set 中的 Compare 参数旨在成为一些可以用 (const tile&, const tile&) 调用的可调用类型。这意味着您可以使用重载 operator() 的仿函数,例如,像这样:

struct Comp {
    bool operator()(const tile& lhs, const tile& rhs) const {
        if (lhs.id < rhs.id) return true;
        if (lhs.id > rhs.id) return false;
        if (lhs.xCord < rhs.xCord) return true;
        if (lhs.xCord > rhs.xCord) return false;
        if (lhs.yCord < rhs.yCord) return true;
        if (lhs.yCord > rhs.yCord) return false;
        return lhs.cost < rhs.cost;
    }
    // or maybe, if this logic already exists:
    bool operator()(const tile& lhs, const tile& rhs) const {
        return lhs < rhs; // invoke tile::operator<(const tile&)
    }
};

...

std::set<tile, Comp> myset;

这样,比较器结构就不需要跟踪任何一个 tile 对象的细节,并且可以删除 costComp 的冗余成员。


如果您希望比较器是可配置的,您可以将成员添加到 Comp 结构定义中,并在实例化集合时在构造函数调用中初始化它们:

struct Comp {
    Comp(bool use_cost = false /* default behavior */) : m_use_cost(use_cost) {}

    bool operator()(const tile& lhs, const tile& rhs) const {
        if (m_use_cost){
            return lhs.cost < rhs.cost;
        } else {
            ...
        }
    }
private:
    const bool m_use_cost;
};

...
// default comparison, won't use cost
std::set<tile, Comp> setA;
// specify custom behaviour
std::set<tile, Comp> setB {Comp{true /* right here */}};

显然,可配置性不限于一个或多个bools。让一些 enum 具有 SortByCostSortByXcoord 这样的值可能是有意义的。或者,您可以有一个单独的函子结构来执行每个操作,但这意味着具有不同比较器的集合将具有不同的类型,并且不能相互复制或移动。