std::set 引用外部值的比较器

std::set Comparator that refer to external value

我有类似的东西

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 到 return 最大 activity 的 ClassA 对象(仅来自有序的对象),从有序集中删除一些 ClassA 对象并在其中插入新对象。

如何删除 unoredered_map 的静态要求?我希望每个 ClassB 对象都有一个 compare_values 引用特定的 activity 哈希映射,但我不知道如何将映射传递给它们。

这是一种方法。请注意,我使用观察者指针而不是引用制作了比较器 copy/moveable:

#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;
}