std::function<>
is a useful wrapper around almost any callable thing, including free functions, lambdas, functors, member functions, results from std::bind
. However, when creating a std::function<>
, one must explicitly specify the function signature as in
(taken from here)
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '
'; }
int num_;
};
void print_num(int i)
{ std::cout << i << '
'; }
struct PrintNum {
void operator()(int i) const
{ std::cout << i << '
'; }
};
// store a free function
std::function<void(int)> f_display = print_num;
// store a lambda
std::function<void()> f_display_42 = []() { print_num(42); };
// store the result of a call to std::bind
std::function<void()> f_display_31337 = std::bind(print_num, 31337);
// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
// store a call to a member function and object
using std::placeholders::_1;
std::function<void(int)> f_add_display2= std::bind( &Foo::print_add, foo, _1 );
// store a call to a member function and object ptr
std::function<void(int)> f_add_display3= std::bind( &Foo::print_add, &foo, _1 );
// store a call to a function object
std::function<void(int)> f_display_obj = PrintNum();
even though the signature could be inferred from the assigned objects. It seems that a natural way to avoid this (which should be quite handy in heavily templated code) is an overloaded function template make_function
(similar in spirit to std::make_pair
or std::make_tuple
), when above examples would simply become
// store a free function
auto f_display = make_function(print_num);
// store a lambda
auto f_display_42 = make_function([](){ print_num(42);});
// store the result of a call to std::bind
auto f_display_31337 = make_function(std::bind(print_num, 31337));
// store a call to a member function
auto f_add_display = make_function(&Foo::print_add);
// store a call to a member function and object
using std::placeholders::_1;
auto f_add_display2 = make_function(std::bind( &Foo::print_add, foo, _1));
// store a call to a member function and object ptr
auto f_add_display3 = make_function(std::bind( &Foo::print_add, &foo, _1));
// store a call to a function object
auto f_display_obj = make_function(PrintNum());
Another possible use case is to get the return type for callable object of any kind
decltype(make_function(function_object))::return_type;
avoiding the traits magic in the answer by Piotr S. to this question.
So, my question: why does the standard not provide this functionality? Can make_function
be implemented without compiler magic? Or would it need compiler magic? (even then the first question remains.)