functional_function

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 인스턴스는 CopyConstructibleCopyAssignable 요구 사항을 만족해요. 저장된 호출 가능 객체를 target이라고 부르며, target이 없으면 empty 상태라고 해요. 빈 std::function을 호출하면 std::bad_function_call 예외가 발생해요.

멤버 타입

타입 정의
result_type R
argument_type (C++17에서 deprecated, C++20에서 제거) sizeof...(Args) == 1이고 TArgs...의 유일한 타입일 때 T
first_argument_type (C++17에서 deprecated, C++20에서 제거) sizeof...(Args) == 2이고 T1Args...의 첫 번째 타입일 때 T1
second_argument_type (C++17에서 deprecated, C++20에서 제거) sizeof...(Args) == 2이고 T2Args...의 두 번째 타입일 때 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::functionnullptr과 비교해요

헬퍼 클래스

클래스 설명
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