본문 바로가기
💻 programming/c++

[c++] functor (function object)

by 연구원-A 2020. 12. 15.
반응형

Functor (Function object)

Functors in C++ - GeeksforGeeks

우선 Functor는 Function과 다르다는 것을 먼저 밝힙니다.

그럼 Functor와 Function은 무엇이 다를까요? 한 번 하나의 인자를 받는 함수를 생각해보세요. 만약 런타임 시간 동안 이 함수에 전달하고 싶은 데이터가 있다면 어떻게 전달할 수 있을까요? 간단한 방법은 전역 변수를 사용하는 것입니다. 그렇지만 누구나 알고 있듯 전역 변수를 사용하는 것은 다른 대안이 없을 때 정말 마지막으로 사용하는 것이 좋습니다.

함수 객체 (Functor; Function object)를 이용하면 이 문제를 해결하면서도 마치 함수나 함수 포인터인 것처럼 다룰 수 있습니다. 이러한 함수 객체를 이용한 방법은 STL을 구현할 때 많이 사용되었습니다.

함수의 한계점

아래 코드는 arr의 값을 하나씩 읽어서 increment 함수의 인자로 전달한 다음 값을 1씩 더하는 소스 코드입니다. 그런데 만약 increment 함수를 변경하지 않고 5를 더하고 싶을 땐 어떻게 해야할까요?

tranfrom의 인자로는 단항 함수 (unary function)만 전달할 수 있기 때문에, increment 함수에 더하고 싶은 숫자 값을 인자로 전달할 수 없습니다. 결국 함수를 또 만들 수 밖에 없습니다.

단항 함수: 인자를 하나 받아서 값을 반환하는 함수
이항 함수: 인자를 두 개 받아서 값을 반환하는 함수

// A C++ program uses transform() in STL to add
// 1 to all elements of arr[]
#include <bits/stdc++.h>
using namespace std;

int increment(int x) { return (x+1); }

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr)sizeof(arr[0]);

    // Apply increment to all elements of arr[] and store the modified elements back in arr[]
    transfrom(arr, arr+n, arr, increment);

    for(int i = 0; i < n; i++) cout << arr[i] << " ";
}

함수 객체 도입

이러한 문제를 해결하기 위해 함수 객체 개념이 도입되었습니다. 함수 객체는 함수처럼 동작하는 c++ 클래스입니다. 함수 객체를 생성하기 위해 우리는 클래스를 정의할 때 overator() 연산자를 오버로딩해야 합니다.

// The line,
MyFunctor(10);

// Is same as
MyFunctor.operator()(10);

함수 객체를 이용하여 기존 함수의 문제를 해결한 예제 코드는 다음과 같습니다.

#include <bits/stdc++.h>
using namespace std;

// A Functor
class increment {
    private:
        int num;
    public:
        increment(int n) : num(n) { }

        // This opeerator overloading enables calling
        // operator function () on objects of increment
        int operator() (int arr_num) const {
            return num + arr_num;
        }
};

// Driver code
int main() {
    in arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    int to_aadd = 5;

    transform(arr, arr+n, arr, increment(to_add));
    for(int i = 0; i < n; i++) { cout << arr[i] << " "; }
}

increment(to_add) 구문이 마치 함수에 인자를 전달하는 것처럼 보이지만 실제로는 다음과 같이 변환됩니다. 오버로딩된 함수 obj()는 단항 함수이므로 transform의 인자로 사용할 수 있습니다.

// The line,
transform(arr, arr+n, arr, increment(to_add));

// is the same as writing below two lines,
// Creating object of increment
increment obj(to_add);

// Calling () on obect
transfomr(arr, arr+n, arr, obj); // obj() will be called, obj() is unary function
반응형

'💻 programming > c++' 카테고리의 다른 글

[c++] template meta programming  (0) 2020.12.15
[c++] variadic template (가변 길이 템플릿)  (0) 2020.12.15
[c++] template specialization  (0) 2020.12.15
[c++] template  (0) 2020.12.15
[c++] any  (0) 2020.12.15

댓글