is_function 에서 함수를 구분하기

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);
}

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다