可调用对象
可调用对象的定义:(满足一个即可)
- 是一个函数指针
- 是一个具有operator()成员函数的类对象(就是仿函数)
- 是一个可被转换为函数指针的类对象
- 是一个类成员(函数)指针
关于一个可被转换为函数指针的类对象的举例:
struct Bar
{
using fr_t = void(*) (void);//返回值为空参数为空的函数指针类型定义为fr_t
static void func(void)
{
//...
}
operator fr_t(void)
{
return func;
}
};
int main()
{
Bar bar;
bar();//调用func
//等价于
bar.operator Bar::fr_t()();
}
bar()调用过程,调用operator fr_t(void),随后返回一个目标函数指针,然后变为func()
是一个类成员(函数)指针举例
struct A
{
int a;
int b;
void mem_func(void)
{
//...
}
};
void fun()
{
}
int main()
{
void (A:: * fun_ptr)(void) = &A::mem_func;
int A::* b_ptr = &A::b;//b_ptr的值为0x00000004
A aa;
(aa.*fun_ptr)();
//fun_ptr(&aa);err
void (*p)(void) = &fun;
p();
}
C+11通过提供function和bind统一了可调用对象的各种操作
function
是一个可调用对象的包装器.他是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象
实现原理:
template<typename R, typename... A>
class myfunction<R(A...)>
{
public:
using PFUNC = R(*)(A...);
myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
R operator()(A... arg)
{
return _pfunc(arg...); // hello(arg)
}
private:
PFUNC _pfunc;
};
使用举例:
void call_when_even(int x,const std::function<void(int>& f)
{
if(!(x&1))
{
f(x);
}
}
void output(int x)
{
std::cout<<x<<" ";
}
int main()
{
for(int i=0;i<10;++i)
{
call_when_even(i,output);//将偶数打印
}
}
bind
bind用来将可调用对象与其参数一起进行绑定,绑定后可使用function进行保存
两大作用:
1.将可调用对象与其参数一起绑定成一个仿函数
2.将多元可调用对象转成一元或者(n-1)元可调用对象,就是先绑定部分参数.
bind1st
可以绑定第一个值,可以将一个二元操作转换为一元操作。
template<class _Fn2>
class binder1st
: public unary_function<typename _Fn2::second_argument_type,
typename _Fn2::result_type>
{ // functor adapter _Func(stored, right)
public:
typedef unary_function<typename _Fn2::second_argument_type,
typename _Fn2::result_type> _Base;
typedef typename _Base::argument_type argument_type;
typedef typename _Base::result_type result_type;
binder1st(const _Fn2& _Func,
const typename _Fn2::first_argument_type& _Left)
: op(_Func), value(_Left)
{ // construct from functor and left operand
}
result_type operator()(const argument_type& _Right) const
{ // apply functor to operands
return (op(value, _Right));
}
result_type operator()(argument_type& _Right) const
{ // apply functor to operands
return (op(value, _Right));
}
protected:
_Fn2 op; // the functor to apply
typename _Fn2::first_argument_type value; // the left operand
};
// TEMPLATE FUNCTION bind1st
template<class _Fn2,
class _Ty> inline
binder1st<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
{ // return a binder1st functor adapter
typename _Fn2::first_argument_type _Val(_Left);
return (binder1st<_Fn2>(_Func, _Val));
}
从上面代码我们可以很简单的发现:
1.返回对象的类型为binder1st.
2.使用typename _Fn2::first_argument_type value;保存了绑定的值。
3._Fn2 op; 定义了被适配的函数。
4.提供调用操作符result_type operator()(argument_type& _Right).
5.调用操作中,使用被适配的函数,第一个值为绑定的值return (op(value, _Right));.
bind
bind返回一个stl内部定义的仿函数类型,可以直接赋给function,一般和占位符搭配使用,
struct A
{
int a;
int b;
void output(int x,int y)
{
cout << x << y << endl;
}
};
int main()
{
A a;
function<void(int, int)> fr = bind(&A::output, &a, placeholders::_1, placeholders::_2);
}