// あるコンテナから指定した条件を満たす要素だけを
// 別のコンテナにコピーする。条件設定を柔軟に。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;


// matching pattern type definition
typedef enum MATCHING_PATTERN_ {
	COMPLETE,
	PARTIAL
} MATCHING_PATTERN;


// predicate
class pred : std::unary_function<string, bool> {
public:
	pred( const char *pcName = "" , MATCHING_PATTERN mp = COMPLETE )
		: name_( pcName ), mp_( mp ) {}
	bool operator()( const string& str ) const {
		bool b_ret = true;
		switch ( mp_ ) {
			case COMPLETE:
				b_ret = ( str != name_ );
				break;
			case PARTIAL:
				b_ret =  ( str.find( name_ ) == str.npos );
				break;
			default:
				b_ret = true;
				break;
		}
		return b_ret;
	}
	void setName( const char *pcName ) {
		name_ = pcName;
	}
	void setMatchingPattern( MATCHING_PATTERN mp ) {
		mp_ = mp;
	}
private:
	string				name_;
	MATCHING_PATTERN	mp_;
};


int
main()
{
	vector<string>	strVec;
	strVec.push_back( "foo" );
	strVec.push_back( "bar" );
	strVec.push_back( "hogehoge" );
	strVec.push_back( "aaa" );
	strVec.push_back( "bbb" );
	strVec.push_back( "ccc" );

	vector<string>	strVec2;
	// copy 1st
	// complete matching ( by ctor )
	remove_copy_if( strVec.begin(),
					strVec.end(),
					back_inserter( strVec2 ),
					pred( "hogehoge" )
					);

	cout << "copied vector size = " << strVec2.size() << endl;
	for ( int i=0; i < strVec2.size( ) ; i++ ) {
		cout << strVec2[i] << endl;
	}

	// copy 2nd
	// complete matching ( setting string by member method )
	pred	pd;
	pd.setName( "bar" );
	remove_copy_if( strVec.begin(),
					strVec.end(),
					back_inserter( strVec2 ),
					pd
					);
	cout << "copied vector size = " << strVec2.size() << endl;
	{	// for foolish VC++ ( /Za option is not effective )
		for ( int i=0; i < strVec2.size( ) ; i++ ) {
			cout << strVec2[i] << endl;
		}
	}

	// copy 3rd
	// partial matching
	pred	pds( "b", PARTIAL );
	remove_copy_if( strVec.begin(),
					strVec.end(),
					back_inserter( strVec2 ),
					pds
					);
	cout << "copied vector size = " << strVec2.size() << endl;
	{	// for foolish VC++ ( /Za option is not effective )
		for ( int i=0; i < strVec2.size( ) ; i++ ) {
			cout << strVec2[i] << endl;
		}
	}

	return 0;
}


	/*
		Predicate に少し融通を持たせた。
		文字列のマッチングに`完全一致'と`部分一致'の 2モードを用意した。
		container00.cpp の例よりはいくらかは実用的かな(^^;
	*/

// end of file