// 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;
}
};
为了实现这个功能,我们需要下面这个组合仿函数:
/**
* 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的用法,进而更深入的介绍了如何写一个复杂点的组合仿函数。