2010-01-05 2 views
8

C++에서 함수의 반환 형식을 추출 (호출하지 않고)하는 방법을 찾고 있습니다. 나는 이것이 약간의 템플릿 마법을 필요로한다고 추정한다.함수를 호출하지 않고 함수의 반환 형식을 추출합니다 (템플릿을 사용합니까?)

float Foo(); 
int Bar(); 

magic_template<Foo>::type var1; // Here 'var1' should be of type 'float' 
magic_template<Bar>::type var2; // and 'var2' should be of type 'int' 

현재 magic_template이 구현 될 수 있지만 지금까지 해결 방법을 찾지 못했습니다.

아이디어가 있으십니까?

답변

7

부스트 type traits 라이브러리를 살펴보고, 특히 function_traits 템플릿은 이러한 기능을 기본 제공합니다. 부스트를 사용할 수 없다면, 코드를 다운로드하고 코드가 어떻게 수행되는지에 대한 통찰력을 얻기 위해 소스를 읽으십시오.

이 기능은 구체적인 기능이 아닌 유형에 기반하므로, 추가 코드를 추가해야 할 수도 있습니다.


는 몇 가지 작은 테스트를 수행 한 후, 이것은 당신이 정말 필요하지 않을 수도 있습니다, 그리고 그것은 '몇 가지 추가 코드'의 경우 사소하지 않은 것입니다. 문제는 function_traits 템플릿이 실제 함수 포인터가 아닌 함수 시그니처에서 작동하므로 문제가 '함수 포인터에서 반환 형식 가져 오기'에서 '함수 포인터에서 서명 가져 오기'로 변경되었는데 그 중 가장 어려운 부분 일 수 있습니다 . 이 같은

+1

함수 반환 유형은 공변량이며 타이타닉을 싱크하는 빙산입니다. –

+0

흠 맞아 보이는이 모양. 모든 사람들에게 예제를 제공하려면 다음과 같이 작동합니다. boost :: function_traits :: type> :: result_type var1; var1 = 3.14f; 내 유일한 문제는 당신이 말했듯이, 나는 이러한 부스트 유틸리티에 전달하기 위해 전체 기능의 유형이 필요합니다. – pauldoo

+0

@nobugz : 나는 당신의 의견을 정말로 이해하지 못합니다, 당신은 더 설명 할 수 있습니까? –

-1

시도 뭔가 : 함수 이름이 표현 유형이 아니기 때문에

template<class T> struct magic_template 
{}; 

template<class T> struct magic_template<T()> 
{ 
    typedef T type; 
}; 
5

그것은 까다로운 - 당신은 GCC의 typeof 뭔가를해야합니다. Boost의 TypeOf은 매우 가까워지는 휴대용 솔루션입니다. 코드가되도록 구성 할 수 있습니다 경우

그러나 작업이 Foo 또는 Bar가 전달 될 수있는 함수 템플릿 내부에서 수행되고, 직선 앞으로 답이있다 :

template <class R> 
void test(R (*)()) 
{ 
    R var1; 
} 

int main() 
{ 
    test(&Foo); 
} 
4

푸과 바는 기능 , 함수 유형이 아니므로 약간의 추가 작업이 필요합니다.

다음은 boost :: function_traits와 BOOST_TYPEOF를 조합 한 솔루션입니다.

#include <boost/typeof/typeof.hpp> 
#include <boost/type_traits.hpp> 

float Foo(); 
int Bar(); 

int main() 
{ 
    boost::function_traits<BOOST_TYPEOF(Foo)>::result_type f = 5.0f; 
    boost::function_traits<BOOST_TYPEOF(Bar)>::result_type i = 1; 
    return i; 
} 

편집 :

  • 이 가장 합리적인 용도에 충분해야한다 (10)까지 모든 인수에 대응하는 기능을 위해 작동합니다.
  • 이렇게 BOOST_TYPEOF를 사용하면 기본 유형을 제공하지 않는 플랫폼에서 작동하므로 합리적으로 이식 가능합니다. dribeas에 의해 제안
0

, 여기에 내가 결국에 온 솔루션 :이 아니다

float Foo(); 
int Bar(); 

template<typename T> Monkey(T) { 
    boost::function_traits< boost::remove_pointer<T>::type >::result_type var1 = ...; 
    // Now do something 
} 

Monkey(Foo); 
Monkey(Bar); 

정확히 내가 내 원래의 질문을 목적으로하지만, 나를 위해 충분히 가까이의 형태.

+0

추가 'typename의 거기에 : typename boost :: function_traits :: result_type –

+0

당신은 서명 void Monkey (T *)를 만들면 remove_pointer를 잃을 수 있습니다. [오, 네가 원숭이의 반환 유형도 놓쳤다] –

1

템플릿 마법을 온다 (더 Boost는 관련 없음) :

template <typename ReturnType> class clFunc0 
{ 
    typedef ReturnType (*FuncPtr)(); 
public: 
    typedef ReturnType Type; 
}; 

template <typename ReturnType> inline clFunc0<ReturnType> ResultType(ReturnType (*FuncPtr)()) 
{ 
    return clFunc0<ReturnType>(); 
} 

#define FUNC_TYPE(func_name) decltype(ResultType(&func_name))::Type 

int test() 
{ 
    return 1; 
} 

int main() 
{ 
    FUNC_TYPE(test) Value = 1; 

    return Value; 
} 

을 그리고

gcc Test.cpp -std=gnu++0x 
통해 컴파일
+1

'std :: result_of'가있는 C++ 11에서는이 작업이 필요 없습니다. – Potatoswatter

관련 문제