std::function can store function pointers (and member function pointers) by value, but using a function-like object that defines operator()—or by extension std::bind()—requires dynamic allocation, which can throw. The templated version, on the other hand, always stores its parameter by value. Come to think of it, you could also make the constructor take an rvalue reference (F&&) to use move construction instead of copy construction.