2009-10-06 2 views
1

누구나 펑터를 도와 줄 수 있는지 궁금합니다. 나는 정말로 펑터가 무엇인지를 이해하지 못한다. 어떻게 작동하는지 나는 인터넷 검색을 시도했다. 그러나 나는 아직도 그것을 얻지 않는다. 펑터는 어떻게 작동하며 템플릿을 사용하는 방법은 무엇입니까?C++ 템플릿이있는 펑터

답변

6

Functor는 기본적으로 "함수 객체"입니다. 클래스 또는 구조체에 래핑 된 단일 함수이고 다른 함수에 전달할 수있는 함수입니다.

함수 호출 연산자 (operator())를 오버로드하는 고유 한 클래스 또는 구조체를 작성하여 작동합니다. 일반적으로 함수의 인수로 함수를 생성하는 functor가있는 곳에서 구현하면됩니다.

std::vector<int> counts; 

지금, 당신은 그 벡터에 포함 된 모든 수를 증가 할 :

는 다음과 같은 있다고 가정합시다. 수동으로 루프를 반복하여 증가 시키거나 펑터를 사용할 수 있습니다. 적절한 펑은,이 경우에는 다음과 같이 보일 것이다 :

struct IncrementFunctor 
{ 
    int operator() (int i) 
    { 
     return i + 1; 
    } 
} 

IncrementFunctor 지금의 정수를 받아 그것을 증가 펑터이다. 카운트에 적용하려면 함수로 인수를 취하는 std :: transform 함수를 사용할 수 있습니다.

std::transform(
    counts.begin(),  // the start of the input range 
    counts.end(),   // the end of the input range 
    counts.begin(),  // the place where transform should place new values. 
          // in this case, we put it right back into the original list. 
    IncrementFunctor()); // an instance of your functor 

구문 IncrementFunctor()는 해당 펑터의 인스턴스를 생성 한 다음 std :: transform으로 직접 전달됩니다. 물론 인스턴스를 로컬 변수로 생성하여 전달할 수는 있지만 훨씬 편리합니다.

이제 템플릿을 참조하십시오. std :: transform에있는 functor의 형식은 템플릿 인수입니다. 이것은 std :: transform이 functor가 어떤 타입인지 알지 못하기 때문입니다. 이에 대한 관심 모두는 그것이

newValue = functor(oldValue); 

컴파일러처럼 뭔가를 할 수있는 정의 피팅 연산자를(),이 템플릿에 대한 꽤 똑똑하고, 종종 템플릿 인자가 무엇인지 스스로 알아낼 수 있다는 것입니다 . 이 경우 컴파일러는 std :: transform에 템플릿 유형으로 정의 된 IncrementFunctor 유형의 매개 변수를 전달한다는 것을 자동으로 인식합니다. 그것은 당신에게 입력 꽤 저장

std::transform<std::vector<int>::iterator, // type of the input iterator 
       std::vector<int>::iterator, // type of the output iterator 
       IncrementFunctor>(   // type of your functor 
    counts.begin(),  // the start of the input range 
    counts.end(),   // the end of the input range 
    counts.begin(),  // the place where transform should place new values. 
          // in this case, we put it right back into the original list. 
    IncrementFunctor()); // an instance of your functor 

: 컴파일러가 자동으로 실제 호출은 다음과 같이 것이라는 점을 인식하고, 그래서 그것은 역시 목록에 대해 동일한 작업을 수행합니다.)

5

펑터 구문이 괄호 안에 선택적 인수리스트와 ()를 추가함으로써, 함수 호출 연산자 불려 호출 할 수있는 것을 /이다.

모든 템플릿이 필요합니다. 템플리트와 관련하여 이것이 호출되는 것은이 구문을 허용하는 것입니다. 즉, 자유 함수 또는 operator()()을 대체하는 클래스의 인스턴스를 허용합니다. ("free"함수는 멤버가 아닌 것입니다. 즉 전역 범위의 함수이거나 이전에 포함 된 네임 스페이스의 범위에있는 함수입니다.) 템플릿 메타 프로그래밍의

외부, 우리는 일반적으로 무료 기능이 AA 펑터라고 말할 및 operator()()을 재정의하는 클래스의 인스턴스에 대한 그 이름을 예약하지 않습니다

C++ 템플릿에서
struct Foo { 
public: 
    void operator()(int i) { // do something } 
    void operator()(int i, char x) { // do something else } 
} 

컴파일 당신이 실제로 _templated_ 펑터의 예를 보여 있기 때문에

template<typename T> class Bar { 
    private int j ; 
    public: 
    Bar(int i) : j(i) {} 
    void doIt(T t) { 
    t(j) ; 
    } 
} 

Foo f; 
extern void resize(int i) ; // in some header 

Bar<Foo> bf(5) ; 
// a Bar that is templated on Foo 
Bar< void (&)(int) > br(5) ; 
// a Bar that is templated on a function taking int and returning void 

br.doit(&resize) ; // call resize with br.j 
bf.doit(f) ; // call Foo::operator()(int) on Foo f with bf.j 
+0

+1, 더 나은 답 : 그래서만큼 구문 이해을 만들면서, 컴파일러는 행복하게 함수 나 펑터를 사용합니다. –

+0

그래도이'void (& (int))'구문은 무엇입니까? 그 사용법은 최소한 C++가 아닙니다. C++/CLI입니까? –

+0

"이 void (& (int)) 구문은 어떻게 되나요?" 예, "int를 가져오고 void를 반환하는 함수의 주소"는 실수입니다. – tpdi

관련 문제