2016-12-31 2 views
2

나는 다음과 같은 일반적인 합계 함수를 작성하고 싶어하지만 템플릿 구문하지만 람다 구문 :C++에서 가변 일반 람다를 사용하여 합계를 계산하는 방법은 무엇입니까?

: 일반 람다 템플릿에 매핑되기 때문에

template<typename T> 
auto Sum(T lastSummand) 
{ 
    return lastSummand; 
} 

template<typename T, typename... Ts> 
auto Sum(T firstSummand, Ts... restSummands) 
{ 
    return firstSummand + Sum(restSummands...); 
} 

이 같은 일을 할 수 있어야한다

auto sum = [](auto firstSummand, auto... restSummands) { ... }; 

하지만 람다를 사용하여 재귀를 수행하는 방법을 알 수 없습니다. 이 위치와 다른 위치에서 검색해도 많은 것을 얻지 못했습니다.

+0

이 당신이 필요로하는 단순한 이유에 대해 작동하지 않습니다 : 당신이 주어진 매개 변수를 산술 유형 모두 즉시 확인하려는 경우 다음과 같이

, 당신은 부울 트릭을 사용할 수 있습니다 최종 사건을 다루기위한 전문화. 최소한 두 개의 람다가 필요합니다. –

+1

요즘 C++이 어디로 가고 싶지 않습니다. –

+0

@Sam Varshavichik : 두 개의 람다를 어떻게 사용합니까? –

답변

4

C++ 14에서는 일반 람다를 사용하여 재귀를 수행 할 필요가 없습니다. 예를 들어
, 당신은이 작업을 수행 할 수 있습니다

#include<type_traits> 
#include<iostream> 

int main() { 
    auto l = [](auto... values) { 
     std::common_type_t<decltype(values)...> ret = {}; 
     decltype(ret) _[] = { (ret += values)... }; 
     (void)_; 
     return ret; 
    }; 

    auto v = l(0, 0., 5, 4.2); 
    std::cout << v << std::endl; 
} 

반환 유형은 주어진 팩의 std::common_type_t에 의해 주어진다.
코드의 나머지 부분은 접기 식을 기다리는 동안 일반적으로 사용되는 공통 패턴을 포함합니다.

C++ 17에서는이 될 것입니다 :

#include<iostream> 

int main() { 
    auto l = [](auto... values) { return (values + ...); }; 
    auto v = l(0, 0., 5, 4.2); 
    std::cout << v << std::endl; 
} 

wandbox에를 참조하십시오.

auto l = [](auto... values) { 
    static_assert(
     std::is_same< 
      std::integer_sequence<bool, true, std::is_arithmetic<decltype(values)>::value...>, 
      std::integer_sequence<bool, std::is_arithmetic<decltype(values)>::value..., true> 
     >::value, "!" 
    ); 

    std::common_type_t<decltype(values)...> ret = {}; 
    decltype(ret) _[] = { (ret += values)... }; 
    (void)_; 
    return ret; 
}; 
+0

decltype (ret) _ [] = {(ret + = values) ...}를 설명해주십시오. (빈)_; 하고있다? –

+0

@KitFisto 임시 배열을 만듭니다 (즉시 삭제됩니다). 이 문장의 목적은'values'를 풀고'ret'에서 그것들을 더하는 것입니다. C++ 17까지는 정상적으로 할 수 없습니다. 유감입니다. – skypjack

+0

그리고 어떻게 (ret + = values) ... 허용됩니까? 그것은 거의 fold 연산자처럼 보입니다. –

0

글쎄, 나는 람다를 사용한다면 합계를 계산하기 위해 펑터 (functor) 형이 필요하다고 가정하고 있습니다. 그렇다면 작은 λ 클래스를 작성하여 그 람다 대신 사용할 수 있다고 가정합니다.

template < typename T > struct Sum 
{ 
    template < typename U > 
    T operator() (U v) const noexcept 
    { 
     return static_cast<T>(v); 
    } 

    template < typename U, typename... Values > 
    T operator() (U v, Values&&... vs) const noexcept 
    { 
     return static_cast<T>(v) + (*this)(std::forward<Values>(vs)...); 
    } 
}; 

그리고 사용 :

auto sum = Sum<int>(); 
printf("%d\n", sum(23, 4.0, true, 7)); 

내가 반환 형식이 사전에 지정 될 수있는 방법을 썼다. 하지만 제네릭을 만들기 위해 그것을 조정할 수 있다고 생각합니다.

귀하의 의도가 아니라면이 대답을 무시하십시오.

+1

답변 해 주셔서 감사합니다. 내 질문의 목적은 템플릿을 명시 적으로 사용하지 않고이를 수행하는 방법이었습니다. –

+0

lambda를 사용하여 구현할 수없는 이유는 특정 매개 변수 집합을 사용하여 람다를 호출하기 때문입니다. 컴파일러는 해당 매개 변수 집합과 일치하는 함수 호출 연산자를 사용하여 Functor와 같은 클래스를 생성합니다. 따라서 동일한 매개 변수 집합을 전달하지 않고도 내부 또는 다른 곳에서 동일한 람다를 호출 할 수 없습니다. 따라서 매개 변수 팩에서 매개 변수를 팝하는 것을 방지 할 수 있습니다. –

관련 문제