2012-07-05 10 views
8

다음과 같은 코드 스 니펫을 사용합니다. 아주 일반적인 코드이지만 좀 더 일반적인 코드에서 사용하려고하는 패턴을 보여줍니다. 모두를 추상화에 std::function의 따라서 사용 :람다 및 std :: 함수를 사용하는 C++ 11 형식 유추

template<typename InT, typename ResT> 
ResT unary_apply(InT val, std::function<ResT(InT)> fn) 
{ 
    return fn(val); 
} 

나는 함수 포인터, 펑, 람다 등으로 unary_apply 호출 할 수 싶습니다.

나는 다음과 같은 방법으로 위를 사용하려고

는, C++ (g ++ 4.7) 관련 타입 추론을 수행 할 수 없습니다 :

double blah = unary_apply(2, [](int v) { return 3.0 * v; }); 

src/fun.cpp:147:75: error: no matching function for call to ‘unary_apply(int, test()::<lambda(int)>)’ 
src/fun.cpp:147:75: note: candidate is: 
src/fun.cpp:137:6: note: template<class InT, class ResT> ResT unary_apply(InT, std::function<ResT(InT)>) 
src/fun.cpp:137:6: note: template argument deduction/substitution failed: 
src/fun.cpp:147:75: note: ‘test()::<lambda(int)>’ is not derived from ‘std::function<ResT(double)>’ 

과 실패를 그리고 난 것을 발견 명시 적으로 템플릿 매개 변수를 지정해야합니다 (실제로는 반환 할 수없는 반환 유형이라고 생각합니다).

double blah = unary_apply<int, double>(2, [](int v) { return 3.0 * v; }); 

C++ 11에서 타입 유추 규칙에 익숙하지 않지만, 위의 동작은 합리적으로 보입니다 (std::function의 내부 메커니즘을 통해 추론하는 것이 아마도 큰 질문 일 수 있음을 알 수 있습니다). 제 질문은 위의 unary_apply 함수를 다시 작성하여 두 번째 매개 변수로 전달할 수있는 함수/펑쳐 등의 유형에 따라 동일한 유연성을 유지하는 것입니다. 또한 유추를 입력하는 데 더 많은 단서를 제공합니다. 그래서 나는 명시 적으로 호출 시점에 템플릿 매개 변수를 제공 할 필요가 없습니까? 작업을해야 조금 더 오리 typey가는

답변

9

:

template <typename T, typename F> 
auto unary_apply(T&& val, F&& func) -> decltype(func(val)) { 
    return func(std::forward<T>(val)); 
} 
+0

제안 된 솔루션이 정확한지는, 첫 번째 문장이 아니다. 타입 추론이 질문에 적용될 수없는 이유는 그것이 람다라는 사실 (다른 펑터/함수를 전달할 수 있고 타입을 추론 할 수 없다는 것)과 관련이 없습니다. –

+0

@ DavidRodríguez-dribeas : 다시 읽습니다. . 람다는 * function * 유형이 아닙니다. 'operator()'를 가지는 이름이없는 클래스 타입입니다. 하지만 네,'std :: function '으로 추측은 어쨌든 작동하지 않을 것입니다. –

+0

나는 그 부분을 놓쳤다. 주석을 고쳤다 : 문제는 람다가 아니라'std :: function'에 대한 템플릿 인자가 uneducable 문맥에 있다는 것입니다. 정규 함수를 전달하십시오 ('std :: function < >'- 아니면 * lambda가'std :: function' 인스턴스화가 아니라는 것을 의미 했습니까?) –

관련 문제