std::set компаратор, который ссылается на внешнее значение

У меня есть что-то вроде

class ClassB {
    // ....
private:
    static std::unordered_map<ClassA,double> activity;
    struct compare_values {
        bool operator()(const ClassA& l, const ClassA& r) const {
            return activity[l] < activity[r];
        }
    };
    std::set<ClassA,compare_values> ordered;
    // ...
}

Поскольку мне нужно, чтобы ClassB возвращал объект ClassA с максимальной активностью (только из упорядоченного объекта), удалите некоторый объект ClassA из упорядоченного набора и вставьте новый внутри.

Как я могу удалить статическое требование для unoredered_map? Я хочу, чтобы у каждого объекта ClassB были Compare_values, которые ссылаются на хэш-карту конкретной активности, но я понятия не имею, как передать им карту.

1 ответ

Решение

Вот один из способов. Обратите внимание, что я сделал копию компаратора / перемещаемую с использованием указателя наблюдателя, а не ссылки:

#include <unordered_map>
#include <set>
#include <memory>

struct ClassA {};
std::size_t hash_value(ClassA const&);
bool operator==(ClassA const&, ClassA const&);

namespace std {
    template<>
    struct hash<::ClassA> {
        template<class Arg>
        auto operator()(Arg&& arg) const {
            return hash_value(arg);
        }
    };
}

class ClassB {

private:
    using activity_map = std::unordered_map<ClassA,double>;

    struct compare_values 
    {
        compare_values(activity_map const& activity)
        : activity_observer_(std::addressof(activity))
        {}

        bool operator()(const ClassA& l, const ClassA& r) const {
            return activity().at(l) < activity().at(r);
        }

    private:

        auto activity() const -> activity_map const&
        {
            return *activity_observer_;
        }

        activity_map const* activity_observer_;
    };
    activity_map activity {};
    std::set<ClassA,compare_values> ordered { compare_values { activity } };
    // ...
};

int main()
{
    ClassB b;
}

по запросу, рефакторинг:

#include <unordered_map>
#include <set>
#include <memory>

struct ClassA {};
std::size_t hash_value(ClassA const&);
bool operator==(ClassA const&, ClassA const&);

namespace std {
    template<>
    struct hash<::ClassA> {
        template<class Arg>
        auto operator()(Arg&& arg) const {
            return hash_value(arg);
        }
    };
}

using ClassA_activity_map = std::unordered_map<ClassA, double>;

struct by_ascending_classA_activity 
{
    by_ascending_classA_activity(ClassA_activity_map const& activity)
    : activity_observer_(std::addressof(activity))
    {}

    bool operator()(const ClassA& l, const ClassA& r) const {
        return activity().at(l) < activity().at(r);
    }

private:

    auto activity() const -> ClassA_activity_map const&
    {
        return *activity_observer_;
    }

    ClassA_activity_map const* activity_observer_;
};


class ClassB {

private:

    ClassA_activity_map activity {};
    std::set<ClassA, by_ascending_classA_activity> ordered { { activity } };
    // ...
};

int main()
{
    ClassB b;
}
Другие вопросы по тегам