std::function<>
是几乎所有可调用事物的有用包装器,包括自由函数、lambda、仿函数、成员函数,结果来自 std::bind
.但是,当创建 std::function<>
,必须明确指定函数签名,如
(取自here)
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;
避免 Piotr S. 对 this question 的回答中的特质魔法.
那么,我的问题是:为什么标准不提供此功能?可以make_function
在没有编译器魔法的情况下实现?还是需要编译器魔法? (即便如此,第一个问题仍然存在。)
最佳答案
class multi_functor
{
public:
void operator()(int) { std::cout << "i'm int" << std::endl }
void operator()(double) { std::cout << "i'm double" << std::endl }
};
int main(void)
{
auto func = make_function(multi_functor());
}
因为这里 func
的类型是什么?
这种歧义适用于所有仿函数对象(包括 bind
返回值和 lambdas),这将使 make_function
仅可用于函数指针。
关于c++ - 为什么没有 std::make_function()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27825559/