Storing functions in a variable in C++ used to be a pain. For example, how would we implement callable such that the code below works?
void foo();
void bar(int arg);
struct some_object
{
void some_method();
};
void test();
{
std::vector<callable> scheduled;
scheduled.push_back(&foo);
// bar with arg = 5.
scheduled.push_back(std::bind(&bar, 5));
some_object c;
scheduled.push_back(std::bind(&some_object::some_method, &c));
// All stored functions can be called as if they were void().
scheduled[0]();
scheduled[1]();
scheduled[2]();
}
Having a working type for all these use cases is a huge task, and before C++11 our only hope were Boost.Function, some other libraries13, or and homemade solution.
A binding like presented in Section 2.5.8 is a partial answer to that but first, it does not even handle member functions, and two, it is already C++11.
<utility>
The std::function type introduced in C++11, in combination with std::bind [?? ], is exactly what we need to fix our previous example. The former is an object that represents a function, and that can be called to invoke this function. It can be a function object or a free function, everything works.
void foo();
void bar(int arg);
struct some_object
{
void some_method();
};
void test();
{
std::vector<std::function<void()>> scheduled;
scheduled.push_back(&foo);
// bar with arg = 5.
scheduled.push_back(std::bind(&bar, 5));
some_object c;
scheduled.push_back(std::bind(&some_object::some_method, &c));
// All stored functions can be called as if they were void().
scheduled[0]();
scheduled[1]();
scheduled[2]();
}
As far as can tell there is only one downside to std::function, it is that every call begins with a test checking if a function is set. If we care about performance, it can be an issue14.
13Search for FastDelegate, the Impossibly Fast C++ Delegates, More Fasterest Delegates, and Ultimate Fast C++ Delegates II’. Some of them may not exist.
14This test is used to throw an std::bad_function_call if the invocation is done on an empty instance. If you wonder why std::function does not reference by default a function that throws the exception, such that no test is done and the exception is still thrown when an empty function is invoked, know that I wonder too. If you have insight about it, I would love to know.