Как мне установить компаратор для набора с ++ - PullRequest
0 голосов
/ 01 октября 2018

У меня есть набор, и для этого набора мне нужны два разных компаратора.Например, для набора 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

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 01 октября 2018

параметр Compare в std::set предназначен для некоторого вызываемого типа, который можно вызывать с помощью (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 со значениями вроде SortByCost, SortByXcoord.В качестве альтернативы у вас может быть отдельная структура функторов, которая выполняет каждый, но это означает, что наборы с разными компараторами будут иметь разные типы и не будут взаимно копируемыми или перемещаемыми.

...