std::bind源码剖析

本文深入剖析C++ STL中的std::bind,讲解如何使用bind进行函数包装,以及bind内部如何通过_Binder类、_Binder::operator()、_Call_binder模板函数等实现函数调用。同时探讨了decay、tuple、make_integer_sequence等C++14特性在bind中的应用。
摘要由CSDN通过智能技术生成

前期准备

  • C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include
  • Copyright (c) by P.J. Plauger. All rights reserved.
  • Consult your license regarding permissions and restrictions.
    V6.50:0009

bind

我们先来研究一下bind,这个bind实际上用途极为广泛,特别是在多线程的程序中,经常用它将函数进行包装,然后打包发送给工作线程,让工作线程去执行我们的任务。

代码范例

#include "stdafx.h"
#include <functional>
using namespace std;

int myfunc(int a, int b, int c )
{
    int d = a + b + c;
    return d;
}

int firstfunc(int a)
{
    int b = a;
    return b;
}
int main()
{
    auto myfunctemp = bind(myfunc, 1,2,3);
    auto myfunctemp2 = bind(firstfunc, 4 );
    myfunctemp();
    myfunctemp2();
    return 0;
}

上面是个函数使用的范例,我们来看一下,模板背后的汇编故事,下面这个是第一个函数myfunc的生成实例。

ConsoleApplication1.exe!
std::bind<int (__cdecl&)(int,int,int),int,int,int>
(
int(*)(int, int, int) _Func, 
int && <_Args_0>, 
int && <_Args_1>, 
int && <_Args_2>
) 行 894     C++
函数头对应的汇编位置为011854C0

接着是第二个函数firstfunc的生成实例

ConsoleApplication1.exe!
std::bind<int (__cdecl&)(int),int>
(int(*)(int) _Func,
int && <_Args_0>
) 行 893
函数头对应的汇编位置为01185460

由此我们发现,根据同一模板,输入不同的特例生成不同的函数,执行不同的实例。
这是我们一种最为简单的bind的使用方法,然后接着我们详细分析一下其后面的逻辑过程。

bind函数

    // TEMPLATE FUNCTION bind (implicit return type)
template<class _Fx,
    class... _Types> inline
    _Binder<_Unforced, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args)
    {   // bind a callable object with an implicit return type
    return (_Binder<_Unforced, _Fx, _Types...>(
        _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...));
    }

    // TEMPLATE FUNCTION bind (explicit return type)
template<class _Ret,
    class _Fx,
    class... _Types> inline
    _Binder<_Ret, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args)
    {   // bind a callable object with an explicit return type
    return (_Binder<_Ret, _Fx, _Types...>(
        _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...));
    }

我们使用bind库的入口就是使用bind模板函数,实际上这个函数将我们传递的函数地址和函数参数做一个包装,构造一个类,返回个类的一个实例。

_Binder类

template<class _Ret,
    class _Fx,
    class... _Types>
    class _Binder
        : public _Binder_result_type<_Ret, _Fx>::type
    {   // wrap bound callable object and arguments
private:
    typedef make_integer_sequence<size_t, sizeof...(_Types)> _Seq;
    typedef typename decay<_Fx>::type _First;
    typedef tuple<typename decay<_Types>::type...> _Second;

    _Compressed_pair<_First, _Second> _Mypair;

public:
    explicit _Binder(_Fx&& _Func, _Types&&... _Args)
        : _Mypair(_One_then_variadic_args_t(),
            _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...)
        {   // construct from forwarded callable object and arguments
        }

#define _BINDER_OPERATOR(CONST_OPT) \
    template<class... _Unbound> \
        auto operator()(_Unbound&&... _Unbargs) CONST_OPT \
        -> decltype(_Call_binder(_Forced<_Ret>(), _Seq(), \
            _Mypair._Get_first(), _Mypair._Get_second(), \
            _STD forward_as_tuple(_STD forward<_Unbound>(_Unbargs)...))) \
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值