2011-10-06 3 views
5

현재 템플릿 기능으로 연습하고 있습니다. 변환 알고리즘의 구현을 작성하는 작업이있었습니다. 나는 다음처럼했고, 작동 : 템플릿이있는 람다

template <class in, class out, class T> 
out stransform(in b, in e, out d, T p(const T&)) { 
    while (b != e) 
     *d++ = p(*b++); 
    return d; 
} 

일반과 마찬가지로 것은 내가 지금

stransform(begin(vec1), end(vec1), back_inserter(vec2), predi<double>); 

처럼 명시 적 유형 술어를 호출해야 변환, 나는 C 우연히 ++ 11 주면서이 같은 내 함수를 호출하고 싶었 : 나는 유형 추론 할 질수 컴파일러 오류를받을 수 있나요 그와

stransform(begin(vec1), end(vec1), back_inserter(vec2), [] (double x) ->double {return x * 10;}); 

합니다. 이것은 내가 실제로 람다에서 T 타입을 두 번 정의하고 있기 때문에 이해하지 못하는 것입니다.

나는 또한 원래의 변환 기능을 확인했다. 그 다음 그 중 implementation을 확인했는데 전체 함수에 대한 템플릿 클래스로 구현되었습니다. 템플릿을 사용하여 술어를 구현하는 올바른 방법입니까? 이 기능에 대한 포인터, 람다와 함수 객체를 받아

template <class in, class out, class UnaryPredicate> 
out stransform(in b, in e, out d, UnaryPredicate p); 

:

답변

13

술어는 일반적으로 간단한 템플릿 인수입니다.

+0

나는 transform의 구현을 읽은 후에 그렇게 생각했다. 나는 아직도 내가 왜 다른 경우에는 작동하지 않는지 궁금해. – inf

+5

@bamboon 람다는 함수가 아니라 함수 객체이기 때문에 상태를 유지할 수 있기 때문에 추측합니다 (함수가 아니라 클로저). –

+1

캡쳐를 수행하지 않는 람다는 일반 함수 (포인터)로 변환 할 수 있습니다. – spraff

2

T p(const T&)T을 참조 번호으로 취하는 함수 유형입니다. 귀하의 람다는 에 의해 인수를 취합니다.

stransform (
    begin (vec1), 
    end (vec1), 
    back_inserter (vec2), 
    [] (const double & x) -> double { 
     return x * 10; 
    }); 

이렇게하면됩니다. 캡처를 수행하지 않는 람다는 일반 함수로 변환 할 수 있습니다.

+1

하지만 함수 포인터에 대한 불필요한 변환에 의존하는 이유는 펑터뿐만 아니라 함수 포인터로도 작업 할 수있는 펑터를 다시 정의 할 수있을 때입니다. – jalf

+0

나를 위해 작동하지 않습니다 (msvc2011 사용). – inf

+0

@jalf functor를 재정의하는 것이 더 나은 해결책입니다. 불변의 라이브러리 코드로이 문제가 발생하면 변환이 가능합니다. – spraff

2

가 분명 적절한 용어를 따로

약간의 전체 기능을위한 템플릿 클래스로 구현됩니다 std::transform 함수 템플릿이 아닌 기능입니다. 더 중요한 것은, 스타일 템플릿을 InputIterator, OutputIteratorFunctor 매개 변수

template<class InputIterator, class OutputIterator, class Functor> 
OutputIterator 
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

의 선언 클래스 유형이 될 필요가 없습니다. 이 예제를 고려하십시오

// function declaration 
int increment(int); 

int array[] = { 0, 1, 2, 3, 4 }; 
transform(std::begin(array), std::end(array), std::begin(array), increment); 

그런 InputIteratorOutputIterator는 클래스 유형입니다 어느 것도, int*Functorint(*)(int) 인 것으로 추론된다 - 훨씬 적은 템플릿 클래스,하지만 난 빗나가 다. 그리고 사실, transform은 단지뿐만 아니라 키워드 typename 좀 더 명확 템플릿 매개 변수의 성격에있다

template<typename InputIterator, typename OutputIterator, typename Functor> OutputIterator transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

를 선언 할 수있다 : 그들은 어떤 성격, 유형입니다.