C++ std::bind(f, ARGS)
bind
binds one or more arguments to a function ...
Synopsis (since C++11, constexpr
since C++20)
template< class F, class... Args > /* unspecified */ bind( F&& f, Args&&... args ); template< class R, class F, class... Args > /* unspecified */ bind( F&& f, Args&&... args );
The function template std::bind
generates a forwarding call wrapper for f. Calling this wrapper is equivalent to invoking f with some of its arguments bound to args.
Example
#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) argument reordering and pass-by-reference: "; int n = 7; // (_1 and _2 are from std::placeholders, and represent future // arguments that will be passed to f1) auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n); n = 10; f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused // makes a call to f(2, 42, 1, n, 7) std::cout << "2) achieving the same effect using a lambda: "; n = 7; auto lambda = [&ncref = n, n](auto a, auto b, auto /*unused*/) { f(b, 42, a, ncref, n); }; n = 10; lambda(1, 2, 1001); // same as a call to f1(1, 2, 1001) std::cout << "3) nested bind subexpressions share the placeholders: "; auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5); f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5); std::cout << "4) bind a RNG with a distribution: "; std::default_random_engine e; std::uniform_int_distribution<> d(0, 10); auto rnd = std::bind(d, e); // a copy of e is stored in rnd for (int n = 0; n < 10; ++n) std::cout << rnd() << ' '; std::cout << '\n'; std::cout << "5) bind to a pointer to member function: "; Foo foo; auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); f3(5); std::cout << "6) bind to a mem_fn that is a pointer to member function: "; 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) bind to a pointer to data member: "; auto f5 = std::bind(&Foo::data, _1); std::cout << f5(foo) << '\n'; std::cout << "8) bind to a mem_fn that is a pointer to data member: "; 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) use smart pointers to call members of the referenced objects: "; std::cout << f6(std::make_shared<Foo>(foo)) << ' ' << f6(std::make_unique<Foo>(foo)) << '\n'; }
std::bind_front
and std::bind_back
(C++20)
Function templates std::bind_front
and std::bind_back
generate a perfect forwarding call wrapper which allows to invoke the callable target with its first or last sizeof
...(Args) parameters bound to args.
These are defined in header <functional>
.
template< class F, class... Args > constexpr /* unspecified */ bind_front( F& f, Args&... args ); // since C++20 template< auto ConstFn, class... Args > constexpr /* unspecified */ bind_front( Args&... args ); // since C++26 template< class F, class... Args > constexpr /* unspecified */ bind_back( F& f, Args&... args ); // since C++23 template< auto ConstFn, class... Args > constexpr /* unspecified */ bind_back( Args&... args ); // since C++26
Example
#include <cassert> #include <functional> int minus(int a, int b) { return a - b; } struct S { int val; int minus(int arg) const noexcept { return val - arg; } }; int main() { auto fifty_minus = std::bind_front(minus, 50); assert(fifty_minus(3) == 47); // equivalent to: minus(50, 3) == 47 auto member_minus = std::bind_front(&S::minus, S{50}); assert(member_minus(3) == 47); //: S tmp{50}; tmp.minus(3) == 47 // Noexcept-specification is preserved: static_assert(!noexcept(fifty_minus(3))); static_assert(noexcept(member_minus(3))); // Binding of a lambda: auto plus = [](int a, int b) { return a + b; }; auto forty_plus = std::bind_front(plus, 40); assert(forty_plus(7) == 47); // equivalent to: plus(40, 7) == 47 #if __cpp_lib_bind_front >= 202306L auto fifty_minus_cpp26 = std::bind_front<minus>(50); assert(fifty_minus_cpp26(3) == 47); auto member_minus_cpp26 = std::bind_front<&S::minus>(S{50}); assert(member_minus_cpp26(3) == 47); auto forty_plus_cpp26 = std::bind_front<plus>(40); assert(forty_plus(7) == 47); #endif #if __cpp_lib_bind_back >= 202202L auto madd = [](int a, int b, int c) { return a * b + c; }; auto mul_plus_seven = std::bind_back(madd, 7); assert(mul_plus_seven(4, 10) == 47); //: madd(4, 10, 7) == 47 #endif #if __cpp_lib_bind_back >= 202306L auto mul_plus_seven_cpp26 = std::bind_back<madd>(7); assert(mul_plus_seven_cpp26(4, 10) == 47); #endif }