현재까지 제안된 방법이 최선일까? 앞서 이야기하기도 했지만 절대 그렇지 않을 것이다. 더 다양한 방법이 있을 수 있을 것이다. 본 포스트에는 좀 더 나은 방법에 대해 기록하며, 그 이외의 다양한 이야기를 적어둘 것이다.
콜백함수를 위한 템플릿을 이용한 2개의 클래스를 사용하는 것 보다 괜찮아 보이는 방법 중 하나는 ‘함수 어댑터(function adaptor)’를 사용하는 방법이다(출처).
// binding function 제작 #include <iostream> #include <cstddef> // 콜백 함수 struct demo { void func() { std::cout << "called.n"; } }; template <typename obj, void (obj::*xptr)() > struct func_bind { static obj x; static void call() { (x.*xptr)(); } }; template <typename obj, void (obj::*xptr)(void) > obj func_bind::x; // 전역변수 콜백 함수 포인터. // 어떤 라이브러리 어딘가에 있다고 가정한다. void (*g_callback)(void) = NULL; int main(int argc, char** argv) { // 라이브러리에 우리의 콜백 함수를 등록하는 과정이라고 가정한다. func_bind<demo, &demo::func> bound; g_callback = bound.call; g_callback(); return EXIT_SUCCESS; }
[그 외 이야기들]
함수 어댑터
멤버 함수를 위한 STL 함수 어댑터들이 있다.mem_fun_ref, mem_fun 들이 그것이다.
#include <functional> demo d; // 멤버 변수를 가진 클래스 std::mem_fun_t<void, demo> p = std::mem_fun<void, demo>(&demo::func); std::mem_fun_ref_t<void, demo> r = std::mem_fun_ref<void, demo>(&demo::func); p(&d); // demo::func 멤버 함수 호출 r(d); // 위와 같으나 위는 객체의 포인터, 이것은 객체의 레퍼런스를 인자로 받는다.
선언된 p나 r은 C-Style callback의 인자로는 사용할 수 없다.
[GLUT Wrapper 등]
- G. Stetten 과 K.Crawford는 GLUT의 C++ wrapper 인 GlutMaster를 만들었다. (홈페이지)
- N. Stewart는 OpenGL C++ Toolkit를 공개했다. (홈페이지)
[Function Object]
- mem_fun, mem_fun_ptr 등은 functional 헤더에 정의되어 있다. 이 외에도 STL은 많은 함수 어댑터를 제공한다. 이들을 이용해 함수형 프로그래밍이 가능하다.
- Boost library는 함수형 프로그래밍 뿐 아니라 C++ 프로그래밍에 있어 유용한 많은 기능을 제공한다. Boost에 대해서는 차후 따로 포스팅할 계획이다.