std :: set引用外部值的Comparator

时间:2017-12-22 09:39:59

标签: c++ stdset

我有类似

的东西
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 个答案:

答案 0 :(得分:2)

这是一种方式。请注意,我已使用观察者指针而不是引用使比较器复制/移动:

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