functional_function (std::function - 다형성 함수 래퍼)
std::function은 C++ 표준 라이브러리에서 제공하는 다형성 함수 래퍼 클래스 템플릿이에요. 이 클래스는 함수 포인터, 람다 표현식, std::bind 결과, 함수 객체, 멤버 함수 포인터, 데이터 멤버 포인터 등 다양한 호출 가능 대상을 저장하고 복사하고 호출할 수 있어요. 이 페이지에서는 std::function의 정의, 멤버 타입, 멤버 함수, 비멤버 함수, 헬퍼 클래스, 주의사항과 예제를 살펴볼게요.
출처: cppreference
본문
std::function은 <functional> 헤더에 정의되어 있어요. 기본 템플릿은 정의되지 않은 상태이며, 호출 시그니처 R(Args...)에 대해 특수화된 형태로 사용해요.
template< class > class function; /* undefined */
template< class R, class... Args > class function<R(Args...)>;
std::function 인스턴스는 CopyConstructible 및 CopyAssignable 요구 사항을 만족해요. 저장된 호출 가능 객체를 target이라고 부르며, target이 없으면 empty 상태라고 해요. 빈 std::function을 호출하면 std::bad_function_call 예외가 발생해요.
멤버 타입
| 타입 |
정의 |
result_type |
R |
argument_type (C++17에서 deprecated, C++20에서 제거) |
sizeof...(Args) == 1이고 T가 Args...의 유일한 타입일 때 T |
first_argument_type (C++17에서 deprecated, C++20에서 제거) |
sizeof...(Args) == 2이고 T1이 Args...의 첫 번째 타입일 때 T1 |
second_argument_type (C++17에서 deprecated, C++20에서 제거) |
sizeof...(Args) == 2이고 T2가 Args...의 두 번째 타입일 때 T2 |
멤버 함수
| 함수 |
설명 |
(constructor) |
새로운 std::function 인스턴스를 생성해요 |
(destructor) |
std::function 인스턴스를 파괴해요 |
operator= |
새로운 target을 할당해요 |
swap |
내용을 교환해요 |
assign (C++17에서 제거) |
새로운 target을 할당해요 |
operator bool |
target이 포함되어 있는지 확인해요 |
operator() |
target을 호출해요 |
target_type |
저장된 target의 typeid를 얻어요 |
target |
저장된 target에 대한 포인터를 얻어요 |
비멤버 함수
| 함수 |
설명 |
std::swap(std::function) (C++11) |
std::swap 알고리즘을 특수화해요 |
operator==, operator!= (C++20에서 제거) |
std::function을 nullptr과 비교해요 |
헬퍼 클래스
| 클래스 |
설명 |
std::uses_allocator<std::function> (C++11, C++17까지) |
std::uses_allocator 타입 특성을 특수화해요 |
추론 가이드 (C++17부터)
주의사항
| 상황 |
설명 |
결과 타입이 참조인 std::function을 후행 반환 타입이 없는 람다 표현식으로 초기화할 때 주의해야 해요. auto 추론 방식 때문에 이러한 람다는 항상 prvalue를 반환해요. 따라서 결과 참조는 보통 std::function::operator()가 반환될 때 수명이 끝나는 임시 객체에 바인딩돼요. |
(C++23까지) |
참조를 반환하는 std::function을 prvalue를 반환하는 함수나 함수 객체(후행 반환 타입이 없는 람다 포함)로 초기화하면, 반환된 참조를 임시 객체에 바인딩하는 것이 금지되므로 프로그램이 ill-formed예요. |
(C++23부터) |
std::function<const int&()> F([] { return 42; }); // Error since C++23: can't bind
// the returned reference to a temporary
int x = F(); // Undefined behavior until C++23: the result of F() is a dangling reference
std::function<int&()> G([]() -> int& { static int i{0x2A}; return i; }); // OK
std::function<const int&()> H([i{052}] -> const int& { return i; }); // OK
예제
#include <functional>
#include <iostream>
struct Foo
{
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_ + i << '\n'; }
int num_;
};
void print_num(int i)
{
std::cout << i << '\n';
}
struct PrintNum
{
void operator()(int i) const
{
std::cout << i << '\n';
}
};
int main()
{
// 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) << "; ";
std::cout << '\n';
}
가능한 출력:
-9
42
31337
314160
314160
num_: 314159
314161
314162
18
5! = 120; 6! = 720; 7! = 5040;
같이 보기
| 항목 |
설명 |
move_only_function (C++23) |
주어진 호출 시그니처에서 한정자를 지원하는 모든 호출 가능 객체의 이동 전용 래퍼 (클래스 템플릿) |
copyable_function (C++26) |
주어진 호출 시그니처에서 한정자를 지원하는 모든 복사 생성 가능한 호출 가능 객체의 복사 가능 래퍼 (클래스 템플릿) |
function_ref (C++26) |
모든 호출 가능 객체의 비소유 래퍼 (클래스 템플릿) |
bad_function_call (C++11) |
빈 std::function을 호출할 때 발생하는 예외 (클래스) |
mem_fn (C++11) |
멤버 포인터로부터 함수 객체를 생성해요 (함수 템플릿) |
typeid |
타입 정보를 조회하고 해당 타입을 나타내는 std::type_info 객체를 반환해요 |
더 알아보기 (Learn more)
cppreference