C 언어에서도 C++, Java 등과 같이 함수를 다른 함수의 인자로 넘겨줄 수 있습니다. 다만, 그 함수는 내부 상태를 가질 수 없다는 것이 한계이죠. 예를 들어, n을 인자로 주면 "항상 n을 리턴하는 함수"를 리턴하는 함수를 만들 수 없죠. 언어 명세 자체에 없는 기능입니다. 하지만 매크로를 이용하면 이걸 구현할 수 있지 않을까요?
#define FUNC_TYPE(type) __func_type_##type
#define FUNC_CAPTURE_TYPE(type) __func_capture_##type
#define DEFINE_FUNC_TYPE(type, return_type, capture_type, ...) \
typedef capture_type FUNC_CAPTURE_TYPE(type); \
typedef struct { \
return_type (*func)(capture_type *capture, __VA_ARGS__); \
capture_type capture; \
} FUNC_TYPE(type); \
return_type type(capture_type *capture, __VA_ARGS__)
#define CAPTURED(name) (capture->name)
#define FUNC_PASS(type, ...) (FUNC_TYPE(type)){ type, (FUNC_CAPTURE_TYPE(type)){ __VA_ARGS__ } }
#define FUNC_CALL(func_obj, ...) (func_obj.func(&func_obj.capture, __VA_ARGS__))
그래서 간단하게 만들어 봤습니다. 아래는 설명이 추가된 예제입니다.
// 캡처된 데이터를 저장하는 구조체
// v
struct foo_capture {
int cap1, cap2, cap3;
};
// 앞서 정의한 구조체
// 리턴값 타입 | 파라메터
// 정의할 함수명 | | ,------|-----,
v v v v v v
DEFINE_FUNC_TYPE(foo, int, struct foo_capture, arg1, arg2, arg3)
{
CAPTURED() 매크로를 사용하여 캡처된 데이터에 접근
v
return CAPTURED(cap1) + CAPTURED(cap2) + CAPTURED(cap3) + arg1 + arg2 + arg3;
}
int func(FUNC_TYPE(foo) func, int arg1, int arg2, int arg3)
{
변수명
함수 호출 | 파라메터
| | ,-----|-----,
v | v v v
return FUNC_CALL(func, arg1, arg2, arg3);
}
int main(void)
{
값 캡처 후 인자로 보내기
v
int value = func(FUNC_PASS(foo, 1, 2, 3), 4, 5, 6);
printf("%d = 21\n", value);
}
불러오는 중...