std::function<>
- полезная оболочка вокруг практически любой вызываемой вещи, включая бесплатные функции, lambdas, функторы, функции-члены, результаты от std::bind
. Однако при создании std::function<>
необходимо явно указать подпись функции, как в
(взято из здесь)
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
void print_num(int i)
{ std::cout << i << '\n'; }
struct PrintNum {
void operator()(int i) const
{ std::cout << i << '\n'; }
};
// 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();
хотя подпись может быть выведена из назначенных объектов. Кажется, что естественным способом избежать этого (что должно быть весьма удобно в сильно шаблоном) является перегруженный шаблон функции make_function
(аналогичный по духу std::make_pair
или std::make_tuple
), когда вышеприведенные примеры просто станут
// 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());
Еще один возможный случай использования - получить возвращаемый тип для вызываемого объекта любого типа
decltype(make_function(function_object))::return_type;
избегая черт черт в ответе Петра С. на этот вопрос.
Итак, мой вопрос: почему стандарт не предоставляет эту функцию? Может ли make_function
быть реализовано без магии компилятора? Или ему понадобится магия компилятора? (даже тогда остается первый вопрос.)