STLの勉強

typedef std::pair	Item;
typedef std::vector	List;
typedef typename List::iterator	iterator;
List	v;

void DoAll( void (*pFunc)(DataType&)) {
	for( iterator it = v.begin(); it!=v.end(); ++it) {
		pFunc( it->second);
	}
}

こんな関数があったらいままでforループのまま放置していたんだけど,forループをfor_eachに置き換えられるはず.ということで挑戦してみた.

なんとなく受け取れる関数の型を変更してみる.余計なことをしている?

template
void DoAll( FnType Fn) {
	for( iterator it = v.begin(); it!=v.end(); ++it) {
		Fn( (*it).second);
	}
}

select2ndがあればpairのsecond側を取得できるらしい.しかしvc8にはselect2ndが無いのでウソくさいselect2ndを定義.

struct select2nd
{
	typename Item::second_type operator()(const Item& x) {
		return x.second;
	}
};

template
void DoAll( FnType Fn) {
	select2nd get2nd;
	for( iterator it = v.begin(); it!=v.end(); ++it) {
		Fn( get2nd(*it));
	}
}

なんかいけそう.compose1があれば関数を合成できるらしい.しかし,compose1もvc8には実装されていない.STLportから適当に引っ張ってくる.

template 
class unary_compose
{
protected:
	_Operation1 _M_fn1;
	_Operation2 _M_fn2;
public:
	unary_compose( _Operation1 fn1, _Operation2 fn2)
		: _M_fn1(fn1), _M_fn2(fn2) {}

	typename _Operation1::result_type
	operator()(const typename _Operation2::argument_type& __x) const {
		return _M_fn1(_M_fn2(__x));
	}
};

template 
inline unary_compose<_Operation1,_Operation2>
compose1(const _Operation1& __fn1, const _Operation2& __fn2)
{
	return unary_compose<_Operation1,_Operation2>(__fn1, __fn2);
}


select2ndも変更する必要が出た.

struct select2nd
{
	typedef Item argument_type;	// 追加
	const typename Item::second_type operator()(const Item& x) const {
		return x.second;
	}
};

引数や返り値の型を自動で定義するためにSTLportは適当な親クラスを継承している? unary_functionとか.(追記:そうらしい.Effective STL 第40項を参照)

ともかく,これでfor_eachに置き換えることができた.

template
void DoAll( FnType Fn) {
	for_each( v.begin(), v.end(), compose1( Fn, select2nd()));
}

vc8の使えなさ加減が勉強にはちょうどいいかもなと思った.