読者です 読者をやめる 読者になる 読者になる

続・C#みたいなFunc、ActionをC++でも使いたい

というわけでついさっきC#みたいなFunc、ActionをC++でも使いたい - プログラム備忘録書きました。
それの続きです

とりあえず作った物を貼り付けて行きます。

  • Func.h
#ifndef __FUNC_H__
#define __FUNC_H__

// Function Delegate class
#define FuncDelegate(arg_num, template_types, args_types, func_arg, use_var) \
template <class Cls, template_types class Ret> \
class Func##arg_num \
{\
	typedef Ret (Cls::*pFunc)(func_arg);\
	pFunc func;\
	Cls c;\
	Ret f(func_arg) {\
		return (c.* func)(use_var);\
	}\
public:\
	Func##arg_num(Cls c, pFunc func) : c(c), func(func) {}\
	Ret operator()(func_arg){return f(use_var);}\
};\
\
template <class Cls, template_types class Ret> \
class Func##arg_num<Cls*, args_types Ret> \
{\
	typedef Ret (Cls::*pFunc)(func_arg);\
	pFunc func;\
	Cls *c;\
	Ret f(func_arg) {\
		return (c->* func)(use_var);\
	}\
public:\
	Func##arg_num(Cls *c, pFunc func) : c(c), func(func) {}\
	Ret operator()(func_arg){return f(use_var);}\
};\
\

// Func0の定義
#define TEMPLATE_TYPES 
#define ARGS_TYPES 
#define FUNC_ARG  
#define USE_VAR   
FuncDelegate(0, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Func1の定義
#define TEMPLATE_TYPES class A1,
#define ARGS_TYPES A1,
#define FUNC_ARG  A1 a1
#define USE_VAR   a1
FuncDelegate(1, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Func2の定義
#define TEMPLATE_TYPES class A1, class A2,
#define ARGS_TYPES A1, A2,
#define FUNC_ARG  A1 a1, A2 a2
#define USE_VAR   a1, a2
FuncDelegate(2, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Func3の定義
#define TEMPLATE_TYPES class A1, class A2, class A3,
#define ARGS_TYPES A1, A2, A3,
#define FUNC_ARG  A1 a1, A2 a2, A3 a3
#define USE_VAR   a1, a2, a3
FuncDelegate(3, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR	

// Func4の定義
#define TEMPLATE_TYPES class A1, class A2, class A3, class A4,
#define ARGS_TYPES A1, A2, A3, A4,
#define FUNC_ARG  A1 a1, A2 a2, A3 a3, A4 a4
#define USE_VAR   a1, a2, a3, a4
FuncDelegate(4, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

#endif
  • Action.h
#ifndef __ACTION_H__
#define __ACTION_H__

#define ActionDelegate(arg_num, template_types, args_types, func_arg, use_var) \
template <class Cls template_types> \
class Action##arg_num \
{\
	typedef void (Cls::*pFunc)(func_arg);\
	pFunc func;\
	Cls c;\
	void f(func_arg) {\
		(c.* func)(use_var);\
	}\
public:\
	Action##arg_num(Cls c, pFunc func) : c(c), func(func) {}\
	void operator()(func_arg){f(use_var);}\
};\
\
template <class Cls template_types> \
class Action##arg_num<Cls* args_types> \
{\
	typedef void (Cls::*pFunc)(func_arg);\
	pFunc func;\
	Cls *c;\
	void f(func_arg) {\
		(c->* func)(use_var);\
	}\
public:\
	Action##arg_num(Cls *c, pFunc func) : c(c), func(func) {}\
	void operator()(func_arg){f(use_var);}\
};\
\

// Action0の定義
#define TEMPLATE_TYPES 
#define ARGS_TYPES 
#define FUNC_ARG  
#define USE_VAR 
ActionDelegate(0, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Action1の定義
#define TEMPLATE_TYPES ,class A1
#define ARGS_TYPES ,A1
#define FUNC_ARG  A1 a1
#define USE_VAR   a1
ActionDelegate(1, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Action2の定義
#define TEMPLATE_TYPES , class A1, class A2
#define ARGS_TYPES , A1, A2
#define FUNC_ARG  A1 a1, A2 a2
#define USE_VAR   a1, a2
ActionDelegate(2, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Action3の定義
#define TEMPLATE_TYPES , class A1, class A2, class A3
#define ARGS_TYPES , A1, A2, A3
#define FUNC_ARG  A1 a1, A2 a2, A3 a3
#define USE_VAR   a1, a2, a3
ActionDelegate(3, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR

// Action4の定義
#define TEMPLATE_TYPES , class A1, class A2, class A3, class A4
#define ARGS_TYPES , A1, A2, A3, A4
#define FUNC_ARG  A1 a1, A2 a2, A3 a3, A4 a4
#define USE_VAR   a1, a2, a3, a4
ActionDelegate(4, TEMPLATE_TYPES, ARGS_TYPES, FUNC_ARG, USE_VAR)
#undef TEMPLATE_TYPES
#undef ARGS_TYPES
#undef FUNC_ARG
#undef USE_VAR


#endif

クラスの関数しか試してません。
static関数やグローバル関数には試してません。
多分クラスの関数にのみ稼動すると思われます。
それぞれ

  • Func##引数の数<[呼び出す関数のクラスの型], [関数の引数の型...], [戻り値の型]>
  • Action##引数の数<[呼び出す関数のクラスの型], [関数の引数の型...]>

となります。

使用例は

#include <stdio.h>
#include "Func.h"
#include "Action.h"

class A { 
public:
	inline double pow(int n) { return n * n; }
	inline void route(char from[], char to[]) { printf("%s から %s までのルート\n", from, to);}
};

int main()
{
	A a;
	// 引数1戻り値ありならFunc1
	Func1<A, int, double> f1(a, &A::pow);
	printf("%lf\n", f1(5));
	// 引数2戻り値なしならAction2
	Action2<A, char[], char[]> f2(a, &A::route);
	f2("札幌", "東京");
}

実行結果は

25.000000
札幌 から 東京 までのルート

となります。
ほかの関数も対応させたいところ。
いい案があったら教えてくださいm(_ _)m