自定义比较器通过显式构造函数排序std :: set [英] Custom comparator via explicit constructor for sorting std::set

查看:176
本文介绍了自定义比较器通过显式构造函数排序std :: set的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组指针,我想以确定性的方式迭代。显然,如果我使用默认排序顺序设置,这将基于指针内存地址,这可能是不同的每次程序运行。所以我定义一个自定义比较器,我想使用,但我不想改变集合的模板类型(因为它在代码中的一百万个地方使用),所以我想传递一个比较器对象到设置构造函数,它源于std :: less

I've got a set of pointers which I would like to iterate over in a deterministic manner. Obviously if I use the default sort order for set, this will be based on the pointers memory addresses which can be different each time the program runs. So I define a custom comparator which I want to use, but I don't want to change the templated type of the set (because it's used in a million places in the code), so I want to pass in a comparator object to the set constructor which is derived from std::less

class TestClass
{
public:
    TestClass(int id_) : id(id_)    {}
    ~TestClass()                    {}
    int  getId() const              { return id;}
    void setId(int id_)             { id = id_; }
private: 
    int id; 
};

struct TestClassLessThan : public std::less<TestClass*>
{   // functor for operator<
    bool operator()(const TestClass* &_Left, const TestClass* &_Right) const
    {   // apply operator< to operands
        return (_Left->getId() < _Right->getId());
    }
};


int main(void)
{
    TestClassLessThan comp; 
    set<TestClass*> testSet(comp), testSet2(comp);

    TestClass* obj1 = new TestClass(1);
    TestClass* obj2 = new TestClass(2);
    testSet.insert(obj1);
    testSet.insert(obj2);

    TestClass* obj = *(testSet.begin());

    cout << "First run" << endl;
    BOOST_FOREACH(TestClass* o, testSet)  // expecting 1,2 - get 1,2
        cout << o->getId() << endl;

    // now change the ordering (based on id) and insert into a new set in the same order
    obj1->setId(3);
    testSet2.insert(obj1);
    testSet2.insert(obj2);

    cout << "Second run" << endl;
    BOOST_FOREACH(TestClass* o, testSet2) // expecting 2,3 - get 3,2
        cout << o->getId() << endl;

    delete obj1;
    delete obj2;
}



因此我的问题是,我忘记了什么?

So my question is, what have I forgotten to do?

推荐答案

以上所有内容都有效。
一个可能的解决方案是使用模板专门化来自定义std :: less本身:

All the above is valid. A possible solution is to customise std::less itself using template specialisation:

namespace std
{
    template<>
    struct less< TestClass*>
    {   // functor for operator<
    public:
        bool operator()(  TestClass* const  &_Left,  TestClass* const  &_Right) const
        {   // apply operator< to operands      
            return (_Left->getId() < _Right->getId());
        }
    };
}

然后使用std :: set的默认模板比较器。

You then get your custom behaviour using the default template comparator for std::set.

根据您的系统构建方式,如果集合在一百万个地方使用并且自定义std :: less不是始终可用,则可能会有问题。

Depending on how you build your system, you may have problems if the set is "used in a million places " and the custom std::less is not consistently available.

这篇关于自定义比较器通过显式构造函数排序std :: set的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆