2 minute read

Categories:

Tags:

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)
  1. 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.
  2. 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