вложенный контейнер set с пользовательским компаратором

#include <functional>
#include <string>
#include <map>
#include <set>

int main()
{
    std::function<bool(const int& lhs, const int& rhs)> comparator
    {
        [](const int& lhs, const int& rhs) -> bool
        {
            return lhs > rhs;
        }
    };

    std::map<std::string, std::set<int, decltype(comparator)>> data;

    data["first"].insert(1);
    data["first"].insert(1);
}

Как в такую связку, где контейнер std::set создаётся неявно, добавить кастомный компаратор?


Ответы (2 шт):

Автор решения: HolyBlackCat

Чтобы не было ненужного оверхеда, я бы не использовал std::function в качестве компаратора, если вам не нужно выбирать один из нескольких компараторов во время выполнения.

В C++20 все просто. Лямбды без списка захвата стали default-constructible, поэтому можно сделать так:

auto comparator = [](const int& lhs, const int& rhs) -> bool
{
    return lhs > rhs;
};

std::map<std::string, std::set<int, decltype(comparator)>> data;

До C++20 можно написать класс с перегруженным () и использовать его как компаратор.

→ Ссылка
Автор решения: Harry

В С++ до С++20 - не хотите просто воспользоваться стандартным компаратором? :)

https://ideone.com/6w9Zmd

map<string, set<int,greater<int>>> data;
data["first"].insert(1);
data["first"].insert(2);
data["first"].insert(7);
data["first"].insert(0);

for(auto x: data["first"])
{
    cout << x << endl;
}

Или обойтись без лямбды:

struct Comps
{
    bool operator()(const int& lhs, const int& rhs)
    {
        return lhs > rhs;
    }
};

map<string, set<int,Comps>> data;

... // Дальше все точно так же

Если не использовать [], то можно так (при этом множество создается явно для вставки с данным ключом):

int main()
{
    auto compar = [](const int& lhs, const int& rhs){ return lhs > rhs; };

    map<string, set<int,decltype(compar)>> data;

    data.insert(make_pair("first",compar));
    data.at("first").insert(1);
    data.at("first").insert(2);
    data.at("first").insert(7);
    data.at("first").insert(0);

    for(auto x: data.at("first"))
    {
        cout << x << endl;
    }
}
→ Ссылка