根据文档(http:/www.cplusplus.comreferencefunctionalfunction),它说
可以将任何一种可调用元素(如函数和函数对象)包装成一个可复制对象的类,其类型仅取决于其调用签名(而不是可调用元素类型本身)。
如何理解类型为 std::function
只取决于它的调用签名(而不是可调用元素类型本身)? 谁能举一些简单的例子来说明一下吗?我很希望能得到一些帮助。
模板类型实际上表示的是函数签名(当然不包括名字)。
std::function<bool(Bar const&, Foo const&)>
可以容纳一个functor、成员函数指针、函数指针或lambda。但可调用的元素必须有 bool (Bar const&, Foo const&)
签名。
class Foo {};
class Bar {};
class FunctorEx
{
public:
bool operator()(Bar const&, Foo const&)
{
return true;
}
} FunctorExInst;
class MemFunction
{
public:
bool MemFunctionEx(Bar const&, Foo const&)
{
return true;
}
} MemFunctionInst;
bool FunctionEx(Bar const&, Foo const&)
{
return true;
}
int main()
{
auto LambdaEx = [] (Bar const&, Foo const&) -> bool
{
return true;
};
std::function<bool(Bar const&, Foo const&)> exFunctionVar;
exFunctionVar = std::bind(&MemFunction::MemFunctionEx, &MemFunctionInst, std::placeholders::_1, std::placeholders::_2);
exFunctionVar = FunctorExInst;
exFunctionVar = FunctionEx;
exFunctionVar = LambdaEx;
}
尽管 MemFunctionInst
, FunctorExInst
, FunctionEx
, LambdaEx
都是不同的类型,它们都可以被分配到相同的。std::function
变量,由于一种叫做 抹杀.
有不同种类的可调用,即函数和漏斗。 std::function
被设计成不管你给它的是哪一种,例如,让我们考虑一个 std::function <void()>
. 在这里,我们说这个函数是一个什么也不返回,什么也不接受的函数,这意味着
void foo() {}
auto bar = []{};
struct { void operator()(){} } baz;
都是可以分配给它的东西,尽管它们都是不同的类型。
这两个 "可调用的元素 "具有相同的调用签名(即。int(float)
),尽管它们有不同的类型。
struct Functor {
int operator()(float arg) {
...
}
};
int function(float arg) {
...
}
这意味着你可以使用相同的 std::function
类型来代表其中之一。
std::function<int(float)> f;
f = Functor();
f = function;
如果我们忘记了所有血淋淋的细节,那么重要的方法是: std::function
是 operator()
.
考虑到你为可调用的对象写了一个包装器,其签名是 double (int,int)
,那么包装器就会是类似的东西。
struct example_wrapper {
double operator()(int a,int b) { return 42; }
};
我省略的细节是让你能够做的 std::function
封装任何类型的可调用对象。如果这些可调用对象具有相同的签名,那么包装器可以具有完全相同的公共接口(即它是相同的类型)。如果这些可调用对象有不同的签名,那么包装器需要一个不同的公共接口(即它是一个不同的类型)。
这意味着简单的说,存储在 std::function
不会影响 std::function
本身,只有函数签名会这样做。
例如,这可以实现这样的非优化。
template<class F, class Ret, class... Args>
Ret invoke_functor(void* func, Args&& ...args)
{
return (*reinterpret_cast<F*>(f))(std::forward<Args>(args)...);
}
template<class Ret, class... Args>
Ret invoke_function(void* func, Args&& ...args)
{
return reinterpret_cast<Ret(*)(Args...)>(func)(std::forward<Args>(args...);
}
template<class Ret, class... Args> //wrong but close enough
class function
{
public:
template<class Functor>
function(Functor&& f) :
m_func(new Functor(f)), //leak
m_invoke(&invoke_functor<Functor, Ret, Args...>)
{ }
function(Ret(*ptr)(Args...)) :
m_func(ptr),
m_invoke(&invoke_function<Ret, Args...>)
{ }
Ret
operator()(const Args& ...args)
{
return m_invoke(m_func, args);
}
private:
void* m_func;
Ret(*m_invoke)(void*, Args...);
}
这里 std::function
可以从函数和可调用结构中创建,如其他答案所示。