C++ STL 学习 :自己写仿函数(functor)(三)

5829阅读 0评论2011-10-12 zieckey
分类:C/C++


    // TEMPLATE STRUCT unary_function
    template<class _Arg, class _Result>
    struct unary_function
    {      // base class for unary functions
        typedef _Arg argument_type;
        typedef _Result result_type;
    };

    template< class _Ty >
    struct visitor : public std::unary_function<_Ty, void>
    {
        void operator()( const _Ty& x )
        {
            std::cout << x << "\t";
        }
    };

这个visitor定义足够简单,我们就不多说了。前文说过for_each的定义,这里再给出来:

    template<typename InputIterator, typename Function>
    Function for_each( InputIterator beg, InputIterator end, Function f ) {
        while ( beg != end )
            f( *beg++ );
    }

看下面的测试代码:

    void test_for_each()
    {   

        typedef std::list<int> intlist;
        intlist il;
        for ( int i = 0; i < 10; i++ )
        {
            il.push_back(i);
        }
        std::for_each( il.begin(), il.end(), visitor<int>() );
    }

这里对一个list进行遍历,对每一个元素调用visitor仿函数。


下面,我们来实现一个复杂点的任务,遍历一个map,对每一个key/value对中value调用visitor仿函数。

首先我们需要一个选择器仿函数select2nd_t来选择key/value对的value:

    /**
     *  select the second parameter from a std::pair
     */
    template< class _Pair >
    struct select2nd_t
        : public std::unary_function< _Pair, typename _Pair::second_type >
    {
        const typename _Pair::second_type& operator()( const _Pair& _x )
        {
            return _x.second;
        }
    };


在遍历过程中,通过select2nd_t把value选出来,然后调用visitor。
为了实现这个功能,我们需要下面这个组合仿函数:

    /**
     *  compose _Func1 and _Func2
     *  use the return value of _Func1 as the parameter of the _Func2 and return the return value of _Func2
     */
    template< class _Func1, class _Func2 >
    struct compose_t
        : public std::unary_function< typename _Func1::argument_type, typename _Func2::result_type >
    {
        _Func1 __func1;
        _Func2 __func2;

        compose_t( const _Func1& f1, const _Func2& f2 ) : __func1(f1), __func2(f2) {}

        typename _Func2::result_type operator()( const typename _Func1::argument_type& _x )
        {
            return __func2( __func1( _x ) );
        }
    };


func1是select2nd_t,func2是visitor。
__func2( __func1( _x ) ) 可以知道,如果 _x 是map里面的单个元素(key/value对,std::pair类型),
先用select2nd_t作用于这个pair得到value,然后做参数传入visitor。

最后,看我们的遍历map中value的函数:

    template< class _Map, class _Func >
    void for_each_2nd( const _Map& _map, const _Func& _func )
    {
        compose_t< select2nd_t< typename _Map::value_type>, _Func > _f( select2nd_t<typename _Map::value_type>(), _func );
        std::for_each( _map.begin(), _map.end(), _f );
    };

通过前面的铺垫,这个函数就比较容易理解了,直接给出使用示例:

    void tset_for_each_2nd()
    {
        typedef std::map<int, int> intmap;
        intmap im;
        for ( int i = 0; i < 10; ++i )
        {
            im.insert( intmap::value_type(i, i * 100) );
        }
    
        for_each_2nd( im, visitor<int>() );
    }


总结:本文介绍了for_each的用法,进而更深入的介绍了如何写一个复杂点的组合仿函数。

上一篇:博客已升级,请注意变更地址
下一篇:map hash_map unordered_map 性能测试