C에서는 함수 포인터/ 콜백 함수라는 것으로 많이 배웠습니다.
이해가 잘 안가고, 매 번 볼 때마다 공부하는 것 같다....
std::function, std::bind를 배우고 나서 진짜 함수 포인터가 쉬워졌습니다.
그러나 사람은 매 번 똑같은 실수를 하지.. stackoverflow에서 사용법만 복붙해서 사용하고 있었습니다.
이런 개발자가 되어서는 안됩니다.
std::function을 제대로 공부하려고, 해당 블로그를 작성합니다.
잘못된 내용이 있을 수 있으니, 꼭 다른 블로그와 교차 검증을 하셔야 합니다.
std::function 이란?
클래스 템플릿 std::function 은 범용 다형 wrapper 함수입니다.
std::function 의 인스턴스는 복사 생성 및 호출 대상 (함수, 람다, 바인딩 또는 다른 함수 객체)을 저장, 복사 및 호출할 수 있으며 멤버 함수에 대한 포인터와 데이터 멤버에 대한 포인터도 호출할 수 있습니다.
다양한 형태의 함수를 "객체" 형태로 저장, 복사, 호출할 수 있다.
내 식대로 이해하면,
객체 형태로써, 함수 포인터 역할을 하고, 그 대상은 바인딩, 람다, 함수 등이 될 수 있다.
비어있는 std::function 객체를 호출하면?
std::bad_function_call 예외가 호출됩니다.
예제코드
#include <iostream>
#include <functional>
class Foo
{
public:
Foo(int num)
: _num(num)
{
}
void print_add(int i) const
{
std::cout << _num + i << '\n';
}
public:
int _num;
};
void print_num(int i)
{
std::cout << i << '\n';
}
class PrintNum {
public:
void operator()(int i) const
{
std::cout << i << '\n';
}
};
int main(void)
{
// store a free function
std::function<void(int)> f_display = print_num;
f_display(-9);
// store a lambda
std::function<void()> f_display_42 = []() { print_num(42); };
f_display_42();
// store the result of a call to std::bind
std::function<void()> f_display_31337 = std::bind(print_num, 31337);
f_display_31337();
// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo(314159);
f_add_display(foo, 1);
f_add_display(314159, 1);
// store a call to a data member accessor
std::function<int(Foo const&)> f_num = &Foo::_num;
std::cout << "_num: " << f_num(foo) << '\n';
// store a call to a member function and object
using std::placeholders::_1;
std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
f_add_display2(2);
// store a call to a member function and object ptr
std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
f_add_display3(3);
// store a call to a function object
std::function<void(int)> f_display_obj = PrintNum();
f_display_obj(18);
auto factorial = [](int n)
{
// store a lambda object to emulate "recursive lambda"; aware of extra overhead
std::function<int(int)> fac = [&](int n) { return (n < 2) ? 1 : n * fac(n - 1); };
// note that "auto fac = [&](int n){...};" does not work in recursive calls
return fac(n);
};
for (int i = 5; i != 8; ++i)
{
std::cout << i << "! = " << factorial(i) << "; ";
}
return 0;
}
당연히 출처에서 코드를 가져왔지만, 다양한 사용방법을 직접 테스트해볼 수 있었습니다.
확실히, C에서 사용했던 함수포인터보다는 사용방법이 다양하고, 직접 짜보니까 std::function이 더 쉬웠습니다.
출처는 https://en.cppreference.com/w/cpp/utility/functional/function 입니다.
'개발 > C++' 카테고리의 다른 글
EBO (Empty Base Optimization) (0) | 2022.07.17 |
---|---|
Copy Elision, RVO (0) | 2022.07.07 |
JsonCpp 사용법 (2) | 2022.02.04 |
map ? unorderd_map ? (0) | 2021.08.09 |
인라인 함수(inline function) (0) | 2021.03.17 |