Using std::bind
Tags: C++
Intro
From cpp reference
template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
(since C++11)
(until C++20)
template< class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );
(since C++20)
(2)
template< class R, class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
(since C++11)
(until C++20)
template< class R, class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );
(since C++20)
- f - indicates any callable object such as function object, pointer to function, reference to function, pointer to member function, or pointer to data member) that will be bound to some arguments.
- args - list of arguments to bind, with the unbound argument replaced by the placeholder _1, _2, _3 … of namespace std::placeholders
std::bind could be found in the <functional>
header file. Now lets examine how this function could be used.
Case 1️⃣
#include <functional>
#include <iostream>
void print(const int& i )
{
std::cout << i << '\n';
}
int main()
{
int i = 5;
const auto f = std::bind(&print, i);
f();
i=6;
f();
}
If the code above is executed, we would see only 5s are printed out twice. This is because one of the thing that bind guarantees to do is make a copy of the arguments passed in. So if we wanted the value to actually track the argument we would need to make a standard reference wrapper like
int main()
{
int i = 5;
const auto f = std::bind(&print, std::ref(i));
f();
i=6;
f();
}
However note that bind is not a light weight function and it needs to be used judiciously.
Case 2️⃣
Now lets say we want the callable object, in this case function, to take multiple arguments but want to print the string that is specified by user.
#include <functional>
#include <iostream>
void print(int i, const std::string& s)
{
std::cout << i << ' ' << s << '\n';
}
int main()
{
int i = 5;
const auto f = std::bind(&print, std::ref(i), std::placeholder::_1);
f("Hello");
i=6;
f("World");
}
case 3️⃣
Binds also let user reorder parameters
int main()
{
int i = 5;
const auto f = std::bind(&print, std::placeholder::_2, std::placeholder::_1);
f("Hello", i);
i=6;
f("World", i);
}
also since bind is designed to swallow all of the extra arguments passed on it, we can do somthing like f("Hello", i, 2, 3, 4, 54, 6)
and we still get the same output
case 4️⃣
If print was a template, we get compiling error. We have to specify the type in order for print to be used in bind function.(ex. &print<int>
)
template<typename T>
void print(T i, const std::string& s)
{
std::cout << i << ' ' << s << '\n';
}
Notes
- Since bind returns callable things, we could pass the result into
std::function<void (const std::string&, int)> f2(f);
- Also try to avoid using std::bind since lamda has better compile time, runtime, memory usage..
Leave a comment