2016-08-28 3 views
5

유형이 있습니다. 해당 목록의 각 유형에 함수를 호출 한 결과와 함께 튜플을 작성한 다음이를 다른 함수에 인수로 사용하고 싶습니다. 이 같은 뭔가 :런타임시 기능이있는 유형 목록 작성

template<typename F> 
struct function_traits; 

template<typename T, typename R, typename... Args> 
struct function_traits<R(T::*)(Args...) const> { 
    using return_type = R; 
    using param_types = std::tuple<Args...>; 
}; 

template<typename T> struct function_traits : public 
function_traits<decltype(&T::operator())> {}; 

template <typename T> 
T* get_arg(int id) 
{ 
    // Actual implementation omitted. Uses the id parameter to 
    // do a lookup into a table and return an existing instance 
    // of type T. 
    return new T(); 
} 

template <typename Func> 
void call_func(Func&& func, int id) 
{ 
    using param_types = function_traits<Func>::param_types>; 

    func(*get_arg<param_types>(id)...); // <--- Problem is this line 
} 

call_func([](int& a, char& b) { }, 3); 

문제는 func(*get_arg<param_types>(id)...); 실제로 param_types 때문에 컴파일되지 않는다는 것입니다 튜플이 아닌 매개 변수 팩입니다. 컴파일러에서 "확장 할 수있는 매개 변수 팩이 없습니다"라는 오류가 발생합니다. 내가 겪었 으면 좋겠던 점은 그 라인이 다음으로 확장되는 것입니다 :

func(*get_arg<int>(id), *get_arg<char>(id)); 

그리고 임의의 수의 인수에 대해 작업 할 수 있습니다. 그 결과를 얻을 수있는 방법이 있습니까?

이 질문은 유사하지만 자체적으로 제 문제를 해결하지는 않습니다 : "unpacking" a tuple to call a matching function pointer. 형식 목록이 있고 거기에서 함수 인수로 사용할 값 목록을 생성하려고합니다. 내가 값의 목록을 가지고 있다면 그것들을 확장 할 수 있고 그 질문에 설명 된대로 함수를 호출 할 수 있지만 나는 그렇지 않다.

+0

''call_func' 내부에서'func'를 호출 할 때 예상되는 결과는 무엇입니까? 모든 인수는'id'와 같아야합니까? 귀하의 예'call_func ([] (int & a, char & b) {}, 3)'lambda의 인수는 무엇입니까? –

+0

id 매개 변수는 실제로 중요하지 않습니다. 내 유스 케이스에서는 get_arg 내부에서 사용하여 반환 할 T의 인스턴스를 찾습니다. 람다에 대한 인수는 필자가 위에서 쓴 것과 유사하게 유형 목록의 각 유형에 대해 get_arg를 호출 한 결과가 될 것입니다. 'func (* get_arg (id), * get_arg (id));' –

+0

가능한 중복 일치하는 함수 포인터를 호출하기 위해 튜플을 언 패킹합니다. (http://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer) – TFM

답변

1

원하는 내용이 확실하지 않습니다. 당신이 헬퍼 구조체의 사용 및 C++ 14 컴파일러를 줄 경우

나는했습니다

..., call_func() 내부 params_type의 매개 변수 팩을 확장하는 방법을 알고 있지만하지 않습니다 반환 유형에 대한 지원과 함께 다음 예제를 준비했습니다.

#include <tuple> 

template<typename F> 
struct function_traits; 

template<typename T, typename R, typename... Args> 
struct function_traits<R(T::*)(Args...) const> { 
    using return_type = R; 
    using param_types = std::tuple<Args...>; 
}; 

template<typename T> struct function_traits : public 
function_traits<decltype(&T::operator())> {}; 

template <typename T, typename ... Args> 
T get_arg (std::tuple<Args...> const & tpl) 
{ return std::get<typename std::decay<T>::type>(tpl); } 

template <typename ...> 
struct call_func_helper; 

template <typename Func, typename Ret, typename ... Args> 
struct call_func_helper<Func, Ret, std::tuple<Args...>> 
{ 
    template <typename T, typename R = Ret> 
     static typename std::enable_if<false == std::is_same<void, R>::value, R>::type 
       fn (Func const & func, T const & t) 
     { return func(get_arg<Args>(t)...); } 

    template <typename T, typename R = Ret> 
     static typename std::enable_if<true == std::is_same<void, R>::value, R>::type 
       fn (Func const & func, T const & t) 
     { func(get_arg<Args>(t)...); } 
}; 

template <typename Func, 
      typename T, 
      typename R = typename function_traits<Func>::return_type> 
R call_func (Func const & func, T const & id) 
{ 
    using param_types = typename function_traits<Func>::param_types; 

    return call_func_helper<Func, R, param_types>::fn(func, id); 
} 

int main() 
{ 
    call_func([](int const & a, char const & b) { }, std::make_tuple(3, '6')); 

    return 0; 
} 

희망이 있습니다.

+0

니스!나는 이것에 대해 내 머리를 감싸 야하지만 이것이 내가 필요한 모든 것을한다고 생각한다. 나는 당신이'>'을 람다의 전문화로 사용할 수 있다는 것에 (놀랍게도) 놀랐다. 나는''functional_traits'에 대한 추악한'R (T :: *) (Args ...) const' 전문화가 필요하다고 생각했을 것입니다. –

관련 문제