일급 함수

 

일급 함수: 아래의 특성을 만족하는 함수

◾ 함수의 인자로 사용될 수 있다.

◾ 변수에 대입할 수 있다.

◾ 함수의 결과값으로 사용될 수 있다. (런타임에 새로운 함수 생성)

◾ 동치(equality)를 정의할 수 있다.

 

한마디로 변수처럼 다룰 수 있는 함수를 의미한다.

 

다른 함수의 매개변수로 함수 전달

typedef std::function<int(int, int)> FuncType; // 함수 객체 타입 재정의

int addition(int x, int y) { ... }
int subtraction(int x, int y) { ... }
int multiplication(int x, int y) { ... }
int division(int x, int y) { ... }
void PassingFunc(FuncType fn, int x, int y) { ... }

...
switch (i) {
    case 1: PassingFunc(addition, a, b); break;
    case 2: PassingFunc(subtraction, a, b); break;
    ...
}

 

함수의 매개 변수로 함수(함수객체)가 전달되어 동작이 다르게 실행된다.

 

 

변수에 함수 대입

typedef std::function<int(int, int)> FuncType; // 함수 객체 타입 재정의

...

FuncType func;

switch (i) {
    case 1: func = addition; break;
    case 2: func = subtracion; break;
    ...
}

std::cout << "Result = " << func(a, b) << '\n';

 

함수 객체를 변수로 만들어서 조건에 따라 함수를 대입하고 이후 함수 호출하듯이 사용하면 된다.

 

 

컨테이너에 함수 저장

typedef std::function<int(int, int)> FuncType;

std::vector<FuncType> functions;

functions.push_back(addition);
functions.push_back(subtraction);
...
std::cout << "Result = " << function.at(i - 1)(a, b) << '\n';

 

 

런타임에 새로운 함수 생성

typedef std::function<double(double)> HyperbolicFunc; // 함수 객체 타입 재정의

std::vector<HyperbolicFunc> funcs = {
    sinh, cosh, tanh, [](double x) { return x*x; }
};
std::vector<HyperbolicFunc> inverseFuncs = {
    asinh, acosh, atanh, [](double x) { return exp(log(x) / 2); }
};

template <typename A, typename B, typename C>
std::function<C(A)> compose(std::function<C(B)> f, std::function<B(A)> g)
{
    return [f, g](A x) { return f(g(x)) };
}


std::vector<HyperbolicFunc> composedFuncs; // 합성 함수가 저장될 컨테이너
std::vector<double> nums;
for (int i = 1; i <= 5; ++i) nums.push_back(i * 0.2);

/* 이항 함수 연산 */
std::transform(std::begin(inverseFuncs), std::end(inverseFuncs),
    std::begin(funcs), std::back_inserter(composedFuncs),
    compose<double, double, double>);

for (auto num : nums) {
    for (auto func : composedFuncs) {
        std::cout << "f(g(" << num << ")) = " << func(num) << '\n';
    }
}

 

 

함수 템플릿은 컴파일 타임에 평가되지만 반환값인 함수 객체는 런타임에 생성된다.

+ Recent posts