C++에서 std::is_function 함수를 다음과 같이 사용해 보면 예상된 결과를 반환해 주지 않습니다.
#include <iostream> #include <type_traits> using namespace std; class A { public: static void static_member_function() { cout << "hello world!!" << endl; } }; int main() { cout << (is_function<decltype(&A::static_member_function)>::value ? "true" : "false") << endl; return 0; }
위 코드의 결과는 "false" 입니다. 함수와 함수 포인터의 차이로 인해서 생기는 이슈 입니다.
is_pointer는 true를 반환하지만 is_function은 false를 반환합니다. 따라서 필요하다면 is_function_pointer 같은 템플릿 함수를 만들어 줄 필요가 있습니다. 물론 예제코드에서 &A::static_member_function 에서 &를 뺀 A::static_member_function을 넘길 경우에는 is_function이 true를 반환합니다. 문제는 함수 포인터를 넘기는 많은 경우 함수 포인터를 받아서 다른 위치에서 함수 포인터를 이용한 호출을 하기 위함입니다.
제가 만난 케이스는 Lua에 값을 바인딩 할 때 함수일 경우와 값일 경우를 구분하기 위해서 사용하는 과정에서 만난 이슈입니다.
template<typename T> void SetGlobal(const char* name, T arg) { std::_If<std::is_function<T>::value, FunctionBinder<T>, // lua에 함수를 바인딩 하는 functor ValueBinder<T> // lua에 변수를 바인딩 하는 functor >::type() (L, name, arg); }
위의 경우 T로 함수 포인터가 넘어오게 되는데 만들고 보니 is_function에서 false가 넘어오길래 다음과 같이 수정하여 해결하였습니다.
template<typename T> void SetGlobal(const char* name, T arg) { std::_If<std::is_pinter<T>::value&&std::is_function<std::remove_pointer<T>::type>::value, FunctionBinder<T>, // lua에 함수를 바인딩 하는 functor ValueBinder<T> // lua에 변수를 바인딩 하는 functor >::type() (L, name, arg); }