3

기본적으로 원하는 것은 Callable (함수 유형/lambda/Functor)을 가져 와서 람다를 반환하는 함수 템플릿을 만드는 것입니다. 당신은 변경할 수 있습니다 - 더 - 유사한 인수 목록을 -taking 원래의 반환 형식C++ 템플릿에서 호출 가능 유형 (인수 목록 및 반환 값)을 추론하는 방법

#include <iostream> 

int func(int a,float b) { 
    return a+b; 
} 

struct callable { 
    int operator() (int a, float b) { 
     return a+b; 
    } 
}; 

template <typename RV, typename... Args> 
auto getLambdaFromCallable(RV(&func)(Args...)) { 
    auto l = [&](Args... args) -> RV { 
     return func(args...); 
    }; 

    return l; 
} 

int main() { 
    auto f = getLambdaFromCallable(func); 
    std::cout << f(1,2.f); 
    std::cout << " " << typeid(f).name(); 

    auto f2 = getLambdaFromCallable(callable{}); // doesn't work 
    callable{}(1,2); // works 

    auto lambdaTest = [](int a, float b) -> int { 
     return a+b; 
    }; 
    auto f3 = getLambdaFromCallable(lambdaTest); 
} 

답변

6

을의 유형을 반환 getLambdaFromCallable에 :

template <typename F> 
auto getLambdaFromFunction(const F& func) { 
    auto l = [&](auto&&... args) 
    -> decltype(func(std::forward<decltype(args)>(args)...)) { 
    return func(std::forward<decltype(args)>(args)...); 
    }; 

    return l; 
} 

이 뒤에 추론은 당신이 철저한를 얻을 수 없기 때문에 함수 객체를 호출 할 수있는 인수 목록 (multip 르 오버로드), 모든 것을 받아들이고 호출 가능하도록 전달하는 일반적인 람다 (lambda)를 사용할 수도 있습니다.


이 작동하는 방법에 대한 자세한 내용을 정교하게하려면 :

  • auto&&... 부분은 람다의 호출 연산자의 템플릿 인수 목록에 변환됩니다.

  • FgetLambdaFromFunction이라고하는 이름으로 추론됩니다 (const 및 참조 번호 없이도 필요에 따라 변경할 수 있음).

  • decltype(args) 차례로 올바르게 앞으로 좌변과를 rvalue 참조 모두, 자세한 내용은 std::forward이 볼 수있는 그냥 std::forward을 사용하는 것입니다.

생성 된 람다 객체가 같이 표시됩니다 : 당신은 그것을 컴파일 할 수 있습니다

#include <functional> 

template <typename OBJ> 
auto getLambdaFromCallable(OBJ&& obj) 
{ 
    return [&](const auto&... args) { 
       return std::invoke(std::forward<OBJ>(obj), args...); 
     }; 
} 

:

template <typename F> 
class generatedLambda 
{ 
public: 
    template <typename... Args> 
    auto operator()(Args&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) 
    { 
    return func(std::forward<decltype(args)>(args)...); 
    } 

private: 
    F  func; 
}; 
+0

람다 (참조를 처리)의 반환 유형에'-> decltype (자동)'. – Jarod42

+0

심지어'-> decltype (func (std :: forward (args) ...))'이므로 SFINAE 친화적입니다. – Jarod42

+0

@ Jarod42 감사합니다. – Drax

2

당신이 C++ (17)를 사용할 수있는 경우, std::invoke 오른쪽 도구입니다 g++ -std=c++17 또는 clang++-5.0 -std=c++1z이며이 기능은 기본적으로 작동합니다.

+0

감사합니다. 매우 편리하고 읽기 쉽게 보입니다. – barney

+1

@ 바니 감사합니다. 나는 인수 전달에 관한 것들을 단순화 한 입력이 수정되지 않았다고 가정했다. 대신에 여기에 간단한 const ref가있다. 나는 또한 모든 세부 사항에서 설명하는 Drax 솔루션을 좋아한다. –

관련 문제