#include <functional>	//for std::is_placeholder<T>

/*#include <boost/bind/arg.hpp>
// ************************************************************************************************
namespace std {
	template <> struct is_placeholder<boost::arg<1>> : integral_constant<int, 1> {};
	template <> struct is_placeholder<boost::arg<2>> : integral_constant<int, 2> {};
	template <> struct is_placeholder<boost::arg<3>> : integral_constant<int, 3> {};
	template <> struct is_placeholder<boost::arg<4>> : integral_constant<int, 4> {};
	template <> struct is_placeholder<boost::arg<5>> : integral_constant<int, 5> {};
	template <> struct is_placeholder<boost::arg<6>> : integral_constant<int, 6> {};
	template <> struct is_placeholder<boost::arg<7>> : integral_constant<int, 7> {};
	template <> struct is_placeholder<boost::arg<8>> : integral_constant<int, 8> {};
	template <> struct is_placeholder<boost::arg<9>> : integral_constant<int, 9> {};
}*/

namespace my	{

struct ILL { ILL(int) {}  typedef ILL first_type; };

//************************************************************************************************
//placeholderなら実引数に変換
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
struct alt_type	{
	typedef typename std::remove_cv<typename std::remove_reference<P>::type>::type naked_param_type;
	static const int N = std::is_placeholder<naked_param_type>::value;
	typedef typename std::conditional<N == 0, P,
						typename std::conditional<N == 1, A1,
							typename std::conditional<N == 2, A2,
								typename std::conditional<N == 3, A3,
									typename std::conditional<N == 4, A4,
										typename std::conditional<N == 5, A5,
											ILL>::type
						>::type>::type>::type>::type>::type
			type;
};
//************************************************************************************************
//引数型と戻値型
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5, int N>
struct func_signature_base;
//フリー関数／メンバ関数の区別と戻値型
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base0	{
	typedef F func_type;
	typedef P1 param1_type; typedef P2 param2_type; typedef P3 param3_type; typedef P4 param4_type; typedef P5 param5_type;
	static F  getF();
	static P1 get1(); static P2 get2(); static P3 get3(); static P4 get4(); static P5 get5();
	//フリー関数は char,   Obj.*mFは short,   pObj->*mFはint  （int********** の'*'の数は引数の数）
	template <typename V> static char
		test(V v, int*****, decltype( v  (get1(), get2(), get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static short
		test(V v, int*****, decltype( (get1().*v)(get2(), get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static int
		test(V v, int*****, decltype((get1()->*v)(get2(), get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static char
		test(V v, int****, decltype( v  (get2(), get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static short
		test(V v, int****, decltype( (get2().*v)(get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static int
		test(V v, int****, decltype((get2()->*v)(get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static char
		test(V v, int***, decltype( v  (get3(), get4(), get5()), (int)0) = 0);
	template <typename V> static short
		test(V v, int***, decltype( (get3().*v)(get4(), get5()), (int)0) = 0);
	template <typename V> static int
		test(V v, int***, decltype((get3()->*v)(get4(), get5()), (int)0) = 0);
	template <typename V> static char
		test(V v, int**, decltype( v  (get4(), get5()), (int)0) = 0);
	template <typename V> static short
		test(V v, int**, decltype( (get4().*v)(get5()), (int)0) = 0);
	template <typename V> static int
		test(V v, int**, decltype((get4()->*v)(get5()), (int)0) = 0);
	template <typename V> static char
		test(V v, int*, decltype(   v  (get5()), (int)0) = 0);
	template <typename V> static short
		test(V v, int*, decltype( (get5().*v)(), (int)0) = 0);
	template <typename V> static int
		test(V v, int*, decltype((get5()->*v)(), (int)0) = 0);
	template <typename V> static char
		test(V v, int, decltype(v(), (int)0) = 0);
	static long test(...);
	//フリー関数かメンバ関数かに応じた戻値型  （int********** の'*'の数は引数の数）
	template <typename V, typename FM> static auto        // FMはフリー関数orメンバ関数の印
		return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(v(get1(), get2(), get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
			->decltype(((get1()).*v)(get2(), get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int*****, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
			->decltype(((get1())->*v)(get2(), get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(     v(get2(), get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
			->decltype((( get2()).*v)(get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int****, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
			->decltype(((get2())->*v)(get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(     v(get3(), get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
			->decltype((( get3()).*v)(get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int***, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
			->decltype(((get3())->*v)(get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(     v(get4(), get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
			->decltype((( get4()).*v)(get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int**, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
			->decltype(((get4())->*v)(get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(       v(get5()));
	template <typename V, typename FM> static auto
		return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, short>::value, V>::type* = 0)
			->decltype((( get5()).*v)());
	template <typename V, typename FM> static auto
		return_t(V v, int*, FM, typename std::enable_if<std::is_same<FM, int>::value, V>::type* = 0)
			->decltype(((get5())->*v)());
	template <typename V, typename FM> static auto
		return_t(V v, int, FM, typename std::enable_if<std::is_same<FM, char>::value, V>::type* = 0)
			->decltype(v());
	static ILL return_t(...);
};
// 5 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 5> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>					B;
	typedef decltype(B::test(B::getF(),(int*****)0))					fm_type;
	typedef decltype(B::return_t(B::getF(), (int*****)0, (fm_type)0))	return_type;
};
// 4 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 4> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>					B;
	typedef decltype(B::test(B::getF(),(int****)0))						fm_type;
	typedef decltype(B::return_t(B::getF(), (int****)0, (fm_type)0))	return_type;
};
// 3 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 3> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>					B;
	typedef decltype(B::test(B::getF(),(int***)0))						fm_type;
	typedef decltype(B::return_t(B::getF(), (int***)0, (fm_type)0))		return_type;
};
// 2 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 2> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>				B;
	typedef decltype(B::test(B::getF(),(int**)0))					fm_type;
	typedef decltype(B::return_t(B::getF(), (int**)0, (fm_type)0))	return_type;
};
// 1 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 1> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>				B;
	typedef decltype(B::test(B::getF(),(int*)0))					fm_type;
	typedef decltype(B::return_t(B::getF(), (int*)0, (fm_type)0))	return_type;
};
// 0 parameters
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
struct func_signature_base<F, P1, P2, P3, P4, P5, 0> : func_signature_base0<F, P1, P2, P3, P4, P5>	{
	typedef func_signature_base0<F, P1, P2, P3, P4, P5>				B;
	typedef decltype(B::test(B::getF(),(int)0))						fm_type;
	typedef decltype(B::return_t(B::getF(), (int)0, (fm_type)0))	return_type;
};
//------------------------------------------------------------------------------------------------
template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5,
					  typename A1, typename A2, typename A3, typename A4, typename A5, int N>
struct func_signature : func_signature_base<typename alt_type<F , A1, A2, A3, A4, A5>::type ,
											typename alt_type<P1, A1, A2, A3, A4, A5>::type ,
											typename alt_type<P2, A1, A2, A3, A4, A5>::type ,
											typename alt_type<P3, A1, A2, A3, A4, A5>::type ,
											typename alt_type<P4, A1, A2, A3, A4, A5>::type ,
											typename alt_type<P5, A1, A2, A3, A4, A5>::type ,
											N												>
{	};
//************************************************************************************************
template <typename P>
struct ParamOf	{
	typedef P param_type;
	typedef typename std::remove_cv<typename std::remove_reference<P>::type>::type naked_param_type;
	static const size_t placeholder = std::is_placeholder<naked_param_type>::value;
	mutable P param;
	ParamOf(P p) : param(p)	{	}
	ParamOf(const ParamOf<P>& p) : param(p.param)	{	}
};
//------------------------------------------------------------------------------------------------
//placeholderだったら実引数に変換する SFINAE
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
typename P::param_type
     pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==0>::type* = 0)
	{	return p->param;	}
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A1&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==1>::type* = 0)
	{	return std::forward<A1>(a1);	}
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A2&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==2>::type* = 0)
	{	return std::forward<A2>(a2);	}
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A3&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==3>::type* = 0)
	{	return std::forward<A3>(a3);	}
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A4&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==4>::type* = 0)
	{	return std::forward<A4>(a4);	}
template <typename P, typename A1, typename A2, typename A3, typename A4, typename A5>
A5&& pass(P* p, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, typename std::enable_if<P::placeholder==5>::type* = 0)
	{	return std::forward<A5>(a5);	}
//************************************************************************************************
template <int N, typename S, typename T = char> struct executer;
//************************************************************************************************
template <typename P, typename T = ILL, typename F = P, int N = 0>
struct BindOf : ParamOf<P>	{
	T			target;
	static const int	depth = N;
	typedef T			target_type;
	typedef F			func_type;
	typedef BindOf<P, T, F, N>								MyT;
	typedef typename ParamOf<P>::param_type					param_type;
	typedef typename std::conditional<N == 0, MyT, T>::type	back_type;
	typedef typename std::conditional<N == 0, MyT, typename T::first_type>::type	first_type;
	BindOf(const P& p) : ParamOf<P>(p), target(0)		{	}	//  bindOfで来る
	BindOf(const P p, T& t) : ParamOf<P>(p), target(t)	{	}	//  << で来る
	BindOf(P p, T&& t) : ParamOf<P>(p), target((T&&)t)	{	}	//  << で来る
	BindOf(MyT&& t) : ParamOf<P>(t), target((T&&)(t.target))	{	}
	back_type* getTarget() const	{ return (depth == 0)? (back_type*)this: (back_type*)&target; }
	first_type* get0() const		{ return (depth == 0)? (first_type*)this: getTarget()->get0(); }
	//
	template <typename A1, typename A2, typename A3, typename A4, typename A5>
	struct mySignature	{
		typedef typename my::func_signature<func_type,
											typename back_type::back_type::back_type::back_type::param_type,
											typename back_type::back_type::back_type::param_type,
											typename back_type::back_type::param_type,
											typename back_type::param_type,
											param_type,
											A1, A2, A3, A4, A5, depth>
						type;
		};
	//bindする変数を追加していく operator <<
	template <typename PN> BindOf<PN, MyT, func_type, depth + 1>
		operator <<(PN&& p)
			{ return BindOf<PN, MyT, func_type, depth + 1>(std::forward<PN>(p), (MyT&&)*this); }
	// ファンクタとしての operator(a,b,c,d,e)
	template <typename A1, typename A2, typename A3, typename A4, typename A5>
		auto operator ()(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5) const
		->typename mySignature<A1, A2, A3, A4, A5>::type::return_type
		{
		typedef typename mySignature<A1, A2, A3, A4, A5>::type		signature;
		executer<depth, signature, typename signature::fm_type>
			theExecuter(pass(get0(), a1, a2, a3, a4, a5));
		return theExecuter
			(
			pass(getTarget()->getTarget()->getTarget()->getTarget(), a1, a2, a3, a4, a5),
			pass(getTarget()->getTarget()->getTarget(), a1, a2, a3, a4, a5),
			pass(getTarget()->getTarget(), a1, a2, a3, a4, a5),
			pass(getTarget(), a1, a2, a3, a4, a5),
			pass(this, a1, a2, a3, a4, a5)
			);
		}
	// ファンクタとしての operator(a,b,c,d)
	template <typename A1, typename A2, typename A3, typename A4>
		auto operator ()(A1&& a1, A2&& a2, A3&& a3, A4&& a4) const
		->typename mySignature<A1, A2, A3, A4, ILL>::type::return_type
		{	return (*this)((A1&&)a1, (A2&&)a2, (A3&&)a3, (A4&&)a4, ILL(0));	}
	// ファンクタとしての operator(a,b,c)
	template <typename A1, typename A2, typename A3>
		auto operator ()(A1&& a1, A2&& a2, A3&& a3) const
		->typename mySignature<A1, A2, A3, ILL, ILL>::type::return_type
		{	return (*this)((A1&&)a1, (A2&&)a2, (A3&&)a3, ILL(0), ILL(0));	}
	// ファンクタとしての operator(a,b)
	template <typename A1, typename A2>
		auto operator ()(A1&& a1, A2&& a2) const
		->typename mySignature<A1, A2, ILL, ILL, ILL>::type::return_type
		{	return (*this)((A1&&)a1, (A2&&)a2, ILL(0), ILL(0), ILL(0));	}
	// ファンクタとしての operator(a)
	template <typename A1>
		auto operator ()(A1&& a1) const
		->typename mySignature<A1, ILL, ILL, ILL, ILL>::type::return_type
		{	return (*this)((A1&&)a1, ILL(0), ILL(0), ILL(0), ILL(0));	}
	// ファンクタとしての operator(void)
	auto operator ()() const
		->typename mySignature<ILL, ILL, ILL, ILL, ILL>::type::return_type
		{	return (*this)(ILL(0), ILL(0), ILL(0), ILL(0), ILL(0));	}
};
//************************************************************************************************
// execute with 5 parameters
template <typename S>
struct executer<5, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function(p1, p2, p3, p4, p5);	}
};
template <typename S>
struct executer<5, S, short>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type Obj,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (Obj.*org_function)(p2, p3, p4, p5);	}
};
template <typename S>
struct executer<5, S, int>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type pObj,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (pObj->*org_function)(p2, p3, p4, p5);	}
};
// execute with 4 parameters
template <typename S>
struct executer<4, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function(p2, p3, p4, p5);	}
};
template <typename S>
struct executer<4, S, short>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type Obj,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (Obj.*org_function)(p3, p4, p5);	}
};
template <typename S>
struct executer<4, S, int>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type pObj,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (pObj->*org_function)(p3, p4, p5);	}
};
// execute with 3 parameters
template <typename S>
struct executer<3, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function(p3, p4, p5);	}
};
template <typename S>
struct executer<3, S, short>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type Obj,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (Obj.*org_function)(p4, p5);	}
};
template <typename S>
struct executer<3, S, int>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type pObj,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return (pObj->*org_function)(p4, p5);	}
};
// execute with 2 parameters
template <typename S>
struct executer<2, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function(p4, p5);	}
};
template <typename S>
struct executer<2, S, short>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type Obj,
										typename S::param5_type p5) const
	{	return (Obj.*org_function)(p5);	}
};
template <typename S>
struct executer<2, S, int>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type pObj,
										typename S::param5_type p5) const
	{	return (pObj->*org_function)(p5);	}
};
// execute with 1 parameters
template <typename S>
struct executer<1, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function(p5);	}
};
template <typename S>
struct executer<1, S, short>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type Obj) const
	{	return (Obj.*org_function)();	}
};
template <typename S>
struct executer<1, S, int>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type pObj) const
	{	return (pObj->*org_function)();	}
};
// execute with 0 parameters
template <typename S>
struct executer<0, S>	{
	typedef typename S::func_type func_type;
	func_type org_function;
	executer(const func_type& f) : org_function(f) { } 
	typename S::return_type operator ()(typename S::param1_type p1,
										typename S::param2_type p2,
										typename S::param3_type p3,
										typename S::param4_type p4,
										typename S::param5_type p5) const
	{	return org_function();	}
};

//************************************************************************************************
//関数ポインタ以外のオブジェクト
template <typename F>
BindOf<typename std::remove_reference<F>::type>
bindOf(F&& f)
{ return BindOf<typename std::remove_reference<F>::type>(std::forward<F>(f)); }

//関数ポインタ
template <typename F>
BindOf<F*>
bindOf(F* f)
{ return BindOf<F*>(f); }
//************************************************************************************************
//ユーザが使う bind関数
template <typename F, typename P1>
auto bind(F&& f, P1&& p1)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1))
{	return bindOf(std::forward<F>(f)) << std::forward<P1>(p1);	}

template <typename F, typename P1, typename P2>
auto bind(F&& f, P1&& p1, P2&& p2)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2))
{	return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2);	}

template <typename F, typename P1, typename P2, typename P3>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3)->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1)
													  << std::forward<P2>(p2) << std::forward<P3>(p3))
{	return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3);	}

template <typename F, typename P1, typename P2, typename P3, typename P4>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3, P4&& p4)
	->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3) << std::forward<P4>(p4))
{	return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3) << std::forward<P4>(p4);	}

template <typename F, typename P1, typename P2, typename P3, typename P4, typename P5>
auto bind(F&& f, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)
	->decltype(bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3)
											<< std::forward<P4>(p4) << std::forward<P5>(p5))
{	return bindOf(std::forward<F>(f)) << std::forward<P1>(p1) << std::forward<P2>(p2) << std::forward<P3>(p3)
										<< std::forward<P4>(p4) << std::forward<P5>(p5);	}

} //namespace my


//************************************************************************************************
//
//************************************************************************************************

int f1(int a)	{ return 1 + a; }
int f2(int a, int& b)	{ return a + (b *= 10); }
int f3(int a, int& b, int c) { return a + (b *= 20) + c; }
int f4(int a, int& b, int c, int& d) { return a + (b *= 30) + c + (d += 30); }
int f5(int a, int& b, int c, int& d, int e) { return a + (b *= 40) + c + (d += 40) + e; }

struct Func	{
	int operator ()() const { return 1000; }
	int operator ()(int a) const { return 1000 + a; }
	int operator ()(int a, int& b) const { return a + (b *= 1000); }
	int operator ()(int a, int& b, int c) const { return a + (b *= 2000) + c; }
	int operator ()(int a, int& b, int c, int& d) const { return a + (b *= 3000) + c + (d += 3000); }
	int func0() const { return (*this)(); }
	int func1(int a) const { return (*this)(a); }
	int func2(int a, int& b) const { return (*this)(a, b); }
	int func3(int a, int& b, int c) const { return (*this)(a, b, c); }
	int func4(int a, int& b, int c, int& d) const { return (*this)(a, b, c, d); }
	};

#include <iostream>

int main() {
	using namespace std::placeholders;
	int b = 1;
	int d = 1;
	int result = 0;
	
	std::cout << "フリー関数 1変数バインド" << std::endl;
	auto bf11 = my::bind(f1, 1);
	result = bf11();
	std::cout << "  f1(1) = " << result << '\n';
	std::cout << "フリー関数 1変数バインドせず" << std::endl;
	auto bf12 = my::bind(f1, _1);
	result = bf12(2);
	std::cout << "  f1(2) = " << result << '\n';
	std::cout << "フリー関数 5変数" << std::endl;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bf51 = my::bind(f5, 1, _1, 8, d, _2);
	result = bf51(b, 3);
	std::cout << "f5(1, b, 8, d, 3) = " << result << "        b = "  << b << ", d = " << d << std::endl;
	std::cout << "ファンクタ 4変数" << std::endl;
	b = d = 1;
	Func fn;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bfn4 = my::bind(fn, 1, _1, 2, _2);
	result = bfn4(b, d);
	std::cout << "fn(1, b, 2, d) = " << result << "        b = "  << b << ", d = " << d << std::endl;
	std::cout << "ファンクタ メンバポインタ" << std::endl;
	b = d = 1;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bfn4m = my::bind(&Func::func4, fn, 1, _1, 2, _2);
	result = bfn4m(b, d);
	std::cout << "fn.*mF(1, b, 2, d) = " << result << "        b = "  << b << ", d = " << d << std::endl;
	b = d = 1;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bfn4mp = my::bind(&Func::func4, &fn, 1, _1, 2, _2);
	result = bfn4mp(b, d);
	std::cout << "fn->*mF(1, b, 2, d) = " << result << "        b = "  << b << ", d = " << d << std::endl;

	b = d = 1;
	std::cout << "第一引数もプレースホルダにできる" << std::endl;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bfn4b1 = my::bind(_1, &fn, 101, _2, 202, _3);
	result = bfn4b1(&Func::func4, b, d);
	std::cout << "fn->*mF(101, b, 202, d) = " << result << "        b = "  << b << ", d = " << d << std::endl;

	b = d = 2;
	std::cout << "どこにでも置ける" << std::endl;
	std::cout << "  b = " << b << ", d = " << d << "      ";
	auto bfn5bF = my::bind(_3, fn, 81, _1, 92, _2);
	result = bfn5bF(b, d, &Func::func4);
	std::cout << "fn.*mF(81, b, 92, d) = " << result << "        b = "  << b << ", d = " << d << std::endl;
	return 0;
}
