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.