Namespaces
Variants

std:: bind

From cppreference.net
Utilities library
Function objects
Function invocation
(C++17) (C++23)
Identity function object
(C++20)
Old binders and adaptors
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* ) ( until C++17* ) ( until C++17* ) ( until C++17* )
( until C++20* )
( until C++20* )
( until C++17* ) ( until C++17* )
( until C++17* ) ( until C++17* )

( until C++17* )
( until C++17* ) ( until C++17* ) ( until C++17* ) ( until C++17* )
( until C++20* )
( until C++20* )
헤더 파일에 정의됨 <functional>
template < class F, class ... Args >
/* unspecified */ bind ( F && f, Args && ... args ) ;
(1) (C++11부터)
(C++20부터 constexpr)
template < class R, class F, class ... Args >
/* unspecified */ bind ( F && f, Args && ... args ) ;
(2) (C++11부터)
(C++20부터 constexpr)

함수 템플릿 std::bind f 에 대한 전달 호출 래퍼를 생성합니다. 이 래퍼를 호출하는 것은 f 를 일부 인자들이 바인딩된 상태로 호출하는 것과 동일합니다. args

만약 std:: is_constructible < std:: decay < F > :: type , F > :: value false 이거나, std:: is_constructible < std:: decay < Arg_i > :: type , Arg_i > :: value false 인 경우 Args 내의 어떤 타입 Arg_i 에 대해서든, 프로그램은 형식에 맞지 않습니다.

만약 std:: decay < Ti > :: type 또는 Args 내의 어떤 타입이 MoveConstructible 또는 Destructible 가 아닌 경우, 동작은 정의되지 않습니다.

목차

매개변수

f - Callable 객체 (함수 객체, 함수 포인터, 함수 참조, 멤버 함수 포인터, 또는 데이터 멤버 포인터)로 일부 인수에 바인딩될 대상
args - 바인딩할 인수 목록으로, 바인딩되지 않은 인수들은 placeholders _1 , _2 , _3 ...로 대체됨 (네임스페이스 std::placeholders 소속)

반환값

지정되지 않은 타입 T 의 함수 객체 g 에 대해, std:: is_bind_expression < T > :: value true 인 경우. 다음과 같은 멤버들을 가집니다:

std::bind 반환 타입

멤버 객체

std::bind 의 반환 타입은 std:: decay < F > :: type 타입의 멤버 객체를 보유하며, 이 객체는 std:: forward < F > ( f ) 로부터 생성됩니다. 또한 args... 각각에 대해 하나의 객체를 보유하며, 이 객체들의 타입은 std:: decay < Arg_i > :: type 이고, 이는 std:: forward < Arg_i > ( arg_i ) 로부터 유사하게 생성됩니다.

생성자

std::bind 의 반환 타입은 CopyConstructible 입니다 - 위에 명시된 모든 멤버 객체가 CopyConstructible일 경우에 한하며, 그렇지 않은 경우에는 MoveConstructible 입니다. 해당 타입은 다음 멤버들을 정의합니다:

멤버 타입 result_type

1) (C++17에서 deprecated 됨) 만약 F 가 함수 포인터 또는 멤버 함수 포인터인 경우, result_type F 의 반환 타입입니다. 만약 F 가 중첩 typedef result_type 을 가진 클래스 타입이라면, result_type F::result_type 입니다. 그 외의 경우에는 result_type 이 정의되지 않습니다.
2) (C++17에서 deprecated 됨) result_type 은 정확히 R 입니다.
(C++20 이전)

멤버 함수 operator()

g 가 함수 호출 표현식 g ( u1, u2, ... uM ) 에서 호출될 때, 저장된 객체의 호출이 다음과 같이 수행됩니다.

1) INVOKE ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) ) , 또는
2) INVOKE<R> ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) ) ,

여기서 fd std:: decay < F > :: type 타입의 값이며, 바인딩된 인수 v1 , v2 , ..., vN 의 값과 타입은 아래 에 명시된 대로 결정됩니다.

g ( ) 호출 시 제공된 인수 중 일부가 g 에 저장된 자리 표시자와 일치하지 않으면, 사용되지 않은 인수들은 평가된 후 폐기됩니다.

operator ( ) 의 호출은, 기반이 되는 INVOKE 연산이 그렇듯이 예외를 발생시키지 않는 경우에만 또는 상수 부분식인 경우에만 (C++20부터) 그렇습니다. operator ( ) INVOKE 연산이 평가되지 않은 피연산자로 취급될 때 올바른 형식인 경우에만 오버로드 해결에 참여합니다.

만약 g volatile -qualified라면, 프로그램은 ill-formed입니다.

만약 INVOKE ( fd, w1, w2, ..., wN ) 표현식이 가능한 모든 값 w1 , w2 , ..., wN 에 대해 유효한 표현식이 될 수 없다면, 동작은 정의되지 않습니다.

바인드된 인수

각 저장된 인수 arg_i 에 대해, INVOKE 또는 INVOKE<R> 연산에서 해당하는 바인딩된 인수 v_i 는 다음과 같이 결정됩니다:

사례 1: 레퍼런스 래퍼

만약 arg_i std:: reference_wrapper < T > 타입인 경우 (예를 들어, std::ref 또는 std::cref std::bind 에 대한 초기 호출에서 사용된 경우), v_i arg_i. get ( ) 이고 그 타입 V_i T& 입니다: 저장된 인자는 참조로 호출된 함수 객체에 전달됩니다.

Case 2: 바인드 표현식

만약 arg_i std:: is_bind_expression < T > :: value true T 타입인 경우(예를 들어, 다른 std::bind 표현식이 std::bind 의 초기 호출에 직접 전달된 경우), std::bind 는 함수 합성을 수행합니다: 바인드 하위 표현식이 반환할 함수 객체를 전달하는 대신, 하위 표현식이 즉시 호출되고 그 반환 값이 외부 호출 가능 객체에 전달됩니다. 바인드 하위 표현식에 placeholder 인자가 있는 경우, 이들은 외부 바인드와 공유됩니다( u1 , u2 , ... 에서 선택됨). 구체적으로, v_i arg_i ( std:: forward < Uj > ( uj ) ... ) 이고 그 타입 V_i std:: result_of < T cv  & ( Uj && ... ) > :: type && (C++17 이전) std:: invoke_result_t < T cv  & , Uj && ... > && (C++17 이후) 입니다(cv 한정자는 g 와 동일함).

Case 3: 플레이스홀더

만약 arg_i T 타입이고, 이에 대해 std:: is_placeholder < T > :: value 0 이 아닌 경우(즉, std::placeholders::_1, _2, _3, ... 와 같은 플레이스홀더가 std::bind 에 대한 초기 호출의 인수로 사용된 경우), 해당 플레이스홀더가 나타내는 인수( _1 에 대한 u1 , _2 에 대한 u2 등)가 호출 가능 객체에 전달됩니다: v_i std:: forward < Uj > ( uj ) 이며, 그 타입 V_i Uj&& 입니다.

Case 4: 일반 인수

그렇지 않으면, arg_i 가 호출 가능 객체에 lvalue 인수로 전달됩니다: v_i 는 단순히 arg_i 이고, 그 타입 V_i T cv  & 입니다. 여기서 cv g 의 cv 한정자와 동일합니다.

예외

std:: decay < F > :: type std:: forward < F > ( f ) 에서 생성하는 과정에서 예외가 발생하거나, std:: decay < Arg_i > :: type 의 생성자 중 어느 하나가 해당하는 std:: forward < Arg_i > ( arg_i ) 에서 예외를 발생시킬 때만 예외를 발생시킵니다. 여기서 Arg_i 는 i번째 타입이고 arg_i Args... args 에서 i번째 인자입니다.

참고 사항

Callable 에서 설명된 바와 같이, 비정적 멤버 함수 포인터나 비정적 데이터 멤버 포인터를 호출할 때 첫 번째 인수는 해당 멤버에 접근할 객체의 참조나 포인터( std::shared_ptr std::unique_ptr 와 같은 스마트 포인터 포함)여야 합니다.

bind에 전달된 인수들은 복사되거나 이동되며, std::ref 또는 std::cref 로 래핑되지 않는 한 참조로 전달되지 않습니다.

동일한 바인드 표현식 내에서 중복된 플레이스홀더(예를 들어 여러 개의 _1 )는 허용되지만, 해당 인수( u1 )가 lvalue 또는 이동 불가능한 rvalue인 경우에만 결과가 명확하게 정의됩니다.

예제

#include <functional>
#include <iostream>
#include <memory>
#include <random>
void f(int n1, int n2, int n3, const int& n4, int n5)
{
    std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
}
int g(int n1)
{
    return n1;
}
struct Foo
{
    void print_sum(int n1, int n2)
    {
        std::cout << n1 + n2 << '\n';
    }
    int data = 10;
};
int main()
{
    using namespace std::placeholders;  // for _1, _2, _3...
    std::cout << "1) 인수 재정렬 및 참조에 의한 전달: ";
    int n = 7;
    // (_1과 _2는 std::placeholders에 있으며, 미래의
    // f1에 전달될 인수들)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1은 _1에 바인딩되고, 2는 _2에 바인딩되며, 1001은 사용되지 않음
                    // f(2, 42, 1, n, 7) 호출을 수행합니다
    std::cout << "2) 람다를 사용하여 동일한 효과 달성: ";
    n = 7;
    auto lambda = [&ncref = n, n](auto a, auto b, auto /*사용되지 않음*/)
    {
        f(b, 42, a, ncref, n);
    };
    n = 10;
    lambda(1, 2, 1001); // f1(1, 2, 1001) 호출과 동일함
    std::cout << "3) 중첩된 bind 하위 표현식은 플레이스홀더를 공유합니다: ";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // f(12, g(12), 12, 4, 5) 호출을 수행합니다;
    std::cout << "4) RNG를 분포와 바인딩하기: ";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // e의 복사본이 rnd에 저장됨
    for (int n = 0; n < 10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
    std::cout << "5) 멤버 함수 포인터에 바인딩: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
    std::cout << "6) 멤버 함수 포인터인 mem_fn에 바인딩: ";
    auto ptr_to_print_sum = std::mem_fn(&Foo::print_sum);
    auto f4 = std::bind(ptr_to_print_sum, &foo, 95, _1);
    f4(5);
    std::cout << "7) 데이터 멤버에 대한 포인터에 바인딩: ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
    std::cout << "8) 데이터 멤버에 대한 포인터인 mem_fn에 바인딩: ";
    auto ptr_to_data = std::mem_fn(&Foo::data);
    auto f6 = std::bind(ptr_to_data, _1);
    std::cout << f6(foo) << '\n';
    std::cout << "9) 참조된 객체의 멤버를 호출하기 위해 스마트 포인터를 사용하십시오: ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

출력:

1) 인수 재정렬 및 참조에 의한 전달: 2 42 1 10 7
2) 람다를 사용하여 동일한 효과 달성: 2 42 1 10 7
3) 중첩된 bind 하위 표현식은 플레이스홀더를 공유함: 12 12 12 4 5
4) 분포를 가진 RNG 바인딩: 0 1 8 5 5 2 0 7 7 10 
5) 멤버 함수 포인터에 바인딩: 100
6) 멤버 함수 포인터인 mem_fn에 바인딩: 100
7) 데이터 멤버 포인터에 바인딩: 10
8) 데이터 멤버 포인터인 mem_fn에 바인딩: 10
9) 참조된 객체의 멤버를 호출하기 위해 스마트 포인터 사용: 10 10

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
LWG 2021 C++11 1. 바운드 인수들이
fd 로 전달되지 않음
2. 경우 2에서, V_i 의 타입이
std:: result_of < T cv  ( Uj... ) > :: type
1. 전달됨
2. 다음으로 변경됨
std:: result_of < T cv  & ( Uj && ... ) > :: type &&

참고 항목

(C++20) (C++23)
가변 개수의 인수를 함수 객체에 순서대로 바인딩
(함수 템플릿)
std::bind 표현식에서 바인딩되지 않은 인수들을 위한 플레이스홀더
(상수)
(C++11)
멤버 포인터로부터 함수 객체 생성
(함수 템플릿)