自定义map的order

我们知道,关联容器map是有序的,比如使用map存储键值对,map的结果是按照int从小到大的顺序排好的。
排序的规则就在于map的第三个参数:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

std::less,它的原型是这样的:

#if _LIBCPP_STD_VER > 11
template <class _Tp = void>
#else
template <class _Tp>
#endif
struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool>
{
    _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 
    bool operator()(const _Tp& __x, const _Tp& __y) const
        {return __x < __y;}
};

看了源码后,我们可以自定义map的新规则:

template <class _Tp>
struct more : binary_function<_Tp, _Tp, bool>
{
    bool operator()(const _Tp& __x, const _Tp& __y) const
        {return __x > __y;}
};

int main()
{
    map<int,string,more<int>> m;
    m[10] = "hello";
    m[11] = "world";
    m[12] = ".";

    for(auto it: m){
        cout<<it.first<<" "<<it.second<<endl;
    }
    return 0;
}
/*
12 .
11 world
10 hello
*/

自定义set order

简单的场景如下,set会自动排好序。

int main()
{
    set<string> sst;

    sst.insert( "hello" );
    sst.insert( "world" );
    sst.insert( "brave" );
    sst.insert( "courage" );

    for(auto it: sst)
    {
        cout << it << endl;
    }
    return 0;
}
/*
brave
courage
hello
world
*/

如果是存储的指针,就需要我们自己书写比较class。
set的构造:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

set对应的binary_function原型为:

#if _LIBCPP_STD_VER > 11
template <class _Tp = void>
#else
template <class _Tp>
#endif
struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool>
{
    _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 
    bool operator()(const _Tp& __x, const _Tp& __y) const
        {return __x < __y;}
};

故,我们可以这样改写默认的less:

template<typename _Tp>
struct ptrLess : binary_function< _Tp, _Tp, bool >
{
    bool operator()(const _Tp& __x, const _Tp& __y) const
        {return *__x < *__y;}
};

int main()
{
    set<string*, ptrLess<string*> > sst;

    sst.insert( new string( "hello" ) );
    sst.insert( new string( "world" ) );
    sst.insert( new string( "brave" ) );
    sst.insert( new string( "courage" ) );

    for(auto it: sst)
    {
        cout << *it << endl;
    }
    return 0;
}

但,ptrLess也不一定必须继承binary_function,只要是一个具有operator()的class即可。
比如,简写成如下形式:

struct ptrLess
{
    template<typename _Tp>
    bool operator()(const _Tp& __x, const _Tp& __y) const
        {return *__x < *__y;}
};

int main()
{
    set<string*, ptrLess > sst;
//...

分类: C plus plus

发表评论

电子邮件地址不会被公开。 必填项已用*标注