Unary Function 은 인자가 1개이며 아무 반환값을 갖는 함수를 말한다.

int test1(int a) ;

char test2(string strText) ;

void test3(char* p) ;

 

위 세 함수 모두 Unary Function 타입이다.

한마디로, 한개의 인자를 가진 함수이다.

 

c++ std::for_each 함수의 원형은 아래와 같다.

namespace std {
    template<class InputIt, class UnaryFunction>
    UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
}

 

복잡한 거 빼고,

위에 적혀있는 Unary Function 에, 한개의 인자를 가진 함수를 변수로 가진다 할 수 있겠다.

 

아래는 예제이다.

♣ for_each() + 함수포인터

#include <cstdio>
#include <algorithm>

using namespace std ;

int printList(int a)
{
        printf("a : %d\n", a) ;
        return 1 ;
}

int main()
{
        int data[5] = {3, 5, 1, 13, 7} ;

        // Unary Function - printList
        // by 함수포인터를 사용한 방법
        for_each(&data[0], &data[4], &printList) ;

        return 1 ;
}

 

printList 함수는 한개의 인자를 가진 함수이므로 Unary Function 이다.

이 함수를 for_each() 함수의 세번째에 함수포인터로 전달하고 있다.

 

그러면 for_each() 함수는 data 배열의 값을 하나씩 printList 함수의 인자로 전달하고,

그 값이 전달될 때마다 printList() 함수는 호출된다.

 

♣ for_each() + 함수객체 (Functor)

함수객체는 굵고 짧게 얘기하면, 클래스 객체를 함수처럼 사용하겠다는 말이다.

예를 들어 아래처럼 test 란 클래스 객체를 생성했다 치자.

MyTest test = MyTest() ;

이 때, test 객체는 보통 아래처럼 쓰인다.

test.init() ;

test.destroy() ;

 

그런데 함수 객체(Functor) 처럼 구현되면 아래처럼 호출할 수 있다.

test(5) ;

test 는 분명 MyTest 클래스의 객체인데 마치 함수처럼 사용되고 있는 것이다.

 

대단하게 썼지만 연산자 오버로딩으로 구현했을 뿐이다.

 

본론으로 돌아와서,

Unary Function 에는 위 함수객체 또한 포함된다.

 

아래는 그 예제이다.

#include <cstdio>
#include <algorithm>

using namespace std ;

class TotalSum
{
public :
        int getSum(){ return sum; } ;

        // 아래 구현된 연산자 오버로딩으로 객체를 함수처럼 사용할 수 있다.
        void operator() (int x)
        {
                sum += x ;
        }

private :
        int sum ;

};

int main()
{
        int data[5] = {3, 5, 1, 13, 7} ;

        // 함수 객체 (Functor) 를 이용한 방법

        // for_each 함수의 반환값은 Unary Function 이다.
        // 함수포인터의 경우, 이 반환값은 무시된다.
        // 하지만 함수객체는 아래처럼 반환값을 받을 수 있다.
        TotalSum temp = TotalSum() ;
        TotalSum sum1 = for_each(&data[0], &data[5], temp) ;
        printf("Sum1 : %d\n", sum1.getSum()) ;

        // 굳이 클래스객체를 생성해서 넘기지 않아도 된다.
        TotalSum sum2 = for_each(&data[0], &data[5], TotalSum()) ;
        printf("Sum2 : %d\n", sum2.getSum()) ;

        return 1 ;
}

 

♣ for_each() + 람다함수 ( Lamda Function)

함수포인터, 함수객체의 경우, main 함수 밖에서 따로 구현된 코드가 존재한다.

람다함수를 사용하면 for_each() 세번째 인자에서 바로 함수를 구현하여

코드를 직관적으로 짤 수 있고 inline 처럼 구현되어 프로그램 실행속도도 빨라진다고 함.

 

람다함수는 나도 아리까리해서 그냥 예제로 퉁친다.

#include <cstdio>
#include <algorithm>

using namespace std ;

int main()
{
        int data[5] = {3, 5, 1, 13, 7} ;

        // Lamda 함수를 이용한 방법
        // Lamda 함수는 함수객체처럼 누적된 변수를 가질 수 없다.
        // C++14 이상의 mutable 을 사용하거나 외부 변수를 사용한다.사용한다
        // 아니면 위와 같이 합을 구하는 경우, accumulate() 함수를 사용할 수 있다.

        // 아래는 Lamda 함수를 사용해 값을 출력하는 방법이다.

        // 한줄 출력
        for_each( &data[0], &data[5], [](int a) { printf("a1 : %d\n", a);});
        printf("===================\n") ;

        // 인자 분해.
        for_each(
                &data[0],
                &data[5],
                [](int a)
                {
                        printf("a2 : %d\n", a);
                }
        );

        return 1 ;
}

 

몇년 전, 당췌 봐도 뭔소리인지 모르던 개념 (Unary Function, functor, 람다함수 등) 이

이제야 살짝 이해가 가서 정리해 본다.

 

+ Recent posts