개념

  • std::bind는 callable 객체의 일부 인자를 고정한 새로운 함수 객체를 생성하는 도구
  • C++ 표준에서 타입을 명확히 지정하지않았으나 operator() 연산자를 재정의한 함수 객체
  • 일반 함수, 멤버 함수, 함수 객체, 람다 모두에 사용 가능
  • C++11에서 도입

예시

using namespace std::placeholders;

void foo(int a, int b, int c, int d) {
 std::println("{} {} {} {}", a, b, c, d);
}

auto f1 = std::bind(&foo, 1, 2, 3, 4);
f1(); // foo(1, 2, 3, 4)

auto f2 = std::bind(&foo, 9, _1, 8, _2);
f2(5, 7); // foo(9, 5, 8, 7)

std::ref

  • 참조 전달이 필요한 경우 std::ref(n) 사용
void foo(int& a);
auto f1 = std::bind(&foo, std::ref(n));

인자로 가능한 형태

  1. 일반 인자
  2. std::ref_wrapper
  3. std::placeholders (_1, _2 …)
  4. 다른 bind expression

Bind Expression

  • std::bind를 또 다른 std::bind의 인자로 넘기는 방식
int mul(int a, int b) { return a * b; }
int add(int a, int b) { return a + b; }

auto f1 = std::bind(&mul, std::bind(&add, _1, _2), 2);
// f1(x, y) == mul(add(x, y), 2)

개선

→ 2번째 인자가 std::is_bind_expression_v에서 true가 나와야 함 https://en.cppreference.com/w/cpp/utility/functional/is_bind_expression

If T is a type produced by a call to std::bind (but not std::bind_front or std:: bind_back), this template is derived from std::true_type. For any other type (unless user-specialized), this template is derived from std::false_type.

int mul(int a, int b) { return a * b; }

struct Add
{
    int operator()(int a, int b) const { return a + b;}
};

template<>
struct std::is_bind_expression<Add> : public std::true_type{};

auto f1 = std::bind(&mul, Add{}, 2);

bind_front (C++20), bind_back (C++23)

  • std::bind의 복잡성과 _2, _1 인덱싱의 혼란을 개선
auto f1 = std::bind(&foo, 0, 0, _1, _2);
auto f2 = std::bind_front(&foo, 0, 0); // 동일한 효과

auto f3 = std::bind(&foo, _1, _2, _3, 0);
auto f4 = std::bind_back(&foo, 0); // 마지막 인자 고정

요약

  • std::bind는 인자를 고정해 새로운 callable 객체를 만들 수 있음
  • 중첩된 표현도 가능하지만 복잡해질 수 있음
  • C++20 이후 std::bind_front, C++23 이후 std::bind_back 사용 권장