文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

浅谈C++11的std::function源码解析

2024-04-02 19:55

关注

1、源码准备

本文是基于gcc-4.9.0的源代码进行分析,std::function是C++11才加入标准的,所以低版本的gcc源码是没有std::function的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不小,但是原理和设计思想的一样的。
源码下载地址:http://ftp.gnu.org/gnu/gcc

2、std::function简介

类模版std::function是一种通用的多态函数包装器。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数指针、类成员函数指针(第一个参数需要传入对应的this指针)、Lambda表达式或者某个类的实例(前提是这个类重载了()运算符)。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。

通常std::function是一个函数对象类,它包装其它任意的可调用实体,被包装的对象具有类型为T1,…,TN的N个参数,并且返回一个可转换到R类型的值。std::function使用模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为std::function。最简单的理解就是通过std::function对C++中各种可调用实体的封装,形成一个新的可调用的std::function对象,让我们不再纠结那么多的可调用实体之间如何进行方便高效的转换。

3、源码解析

3.1、std::function解析

std::function位于libstdc++-v3\include\std\functional中


template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)> : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, private _Function_base
{
    typedef _Res _Signature_type(_ArgTypes...);

    template<typename _Functor>
    using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())(std::declval<_ArgTypes>()...) );

    template<typename _Functor>
    using _Callable = __check_func_return_type<_Invoke<_Functor>, _Res>;

    template<typename _Cond, typename _Tp>
    using _Requires = typename enable_if<_Cond::value, _Tp>::type;

public:
    typedef _Res result_type;

    function() noexcept
        :_Function_base()
    {
    }

    function(nullptr_t) noexcept
        :_Function_base()
    {
    }

    template<typename _Res, typename... _ArgTypes>
    function(const function& __x)
        :_Function_base()
    {
        if (static_cast<bool>(__x))
        {
            _M_invoker = __x._M_invoker;
            _M_manager = __x._M_manager;
            __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
        }
    }

    function(function&& __x)
        :_Function_base()
    { __x.swap(*this); }

    template<typename _Functor, typename = _Requires<_Callable<_Functor>, void>>
    function(_Functor __f)
    {
        typedef _Function_handler<_Signature_type, _Functor> _My_handler;

        if (_My_handler::_M_not_empty_function(__f))
        {
            _My_handler::_M_init_functor(_M_functor, std::move(__f));
            _M_invoker = &_My_handler::_M_invoke;
            _M_manager = &_My_handler::_M_manager;
        }
    }

    function& operator=(const function& __x)
    {
        function(__x).swap(*this);
        return *this;
    }

    function& operator=(function&& __x)
    {
        function(std::move(__x)).swap(*this);
        return *this;
    }

    function& operator=(nullptr_t)
    {
        if (_M_manager)
        {
            _M_manager(_M_functor, _M_functor, __destroy_functor);
            _M_manager = 0;
            _M_invoker = 0;
        }
        return *this;
    }

    template<typename _Functor>
    _Requires<_Callable<_Functor>, function&> operator=(_Functor&& __f)
    {
        function(std::forward<_Functor>(__f)).swap(*this);
        return *this;
    }

    template<typename _Functor>
    function& operator=(reference_wrapper<_Functor> __f) noexcept
    {
        function(__f).swap(*this);
        return *this;
    }

    void swap(function& __x)
    {
        std::swap(_M_functor, __x._M_functor);
        std::swap(_M_manager, __x._M_manager);
        std::swap(_M_invoker, __x._M_invoker);
    }

     explicit operator bool() const noexcept
     { return !_M_empty(); }

    _Res operator()(_ArgTypes... __args) const;
    {
        if (_M_empty())
            __throw_bad_function_call();
        return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
    }

private:
    typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
    _Invoker_type _M_invoker;

从源代码中可以看出以下几点信息:

3.2、std::_Function_handler解析

std::_Function_handler位于libstdc++-v3\include\std\functional中


template<typename _Res, typename _Functor, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
{
    typedef _Function_base::_Base_manager<_Functor> _Base;

public:
    static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        return (*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
    }
};

template<typename _Functor, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
{
    typedef _Function_base::_Base_manager<_Functor> _Base;

public:
    static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        (*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
    }
};

template<typename _Res, typename _Functor, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
{
    typedef _Function_base::_Ref_manager<_Functor> _Base;

public:
    static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        return __callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
    }
};

template<typename _Functor, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
{
    typedef _Function_base::_Ref_manager<_Functor> _Base;

public:
    static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        __callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
    }
};

template<typename _Class, typename _Member, typename _Res, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Member _Class::*> : public _Function_handler<void(_ArgTypes...), _Member _Class::*>
{
    typedef _Function_handler<void(_ArgTypes...), _Member _Class::*> _Base;

public:
    static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        return std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
    }
};

template<typename _Class, typename _Member, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), _Member _Class::*> : public _Function_base::_Base_manager<_Simple_type_wrapper< _Member _Class::* > >
{
    typedef _Member _Class::* _Functor;
    typedef _Simple_type_wrapper<_Functor> _Wrapper;
    typedef _Function_base::_Base_manager<_Wrapper> _Base;

public:
    static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
    {
        switch (__op)
        {
            #ifdef __GXX_RTTI
            case __get_type_info:
                __dest._M_access<const type_info*>() = &typeid(_Functor);
                break;
            #endif

            case __get_functor_ptr:
                __dest._M_access<_Functor*>() = &_Base::_M_get_pointer(__source)->__value;
                break;

            default:
                _Base::_M_manager(__dest, __source, __op);
        }
        return false;
    }

    static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
    {
        std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
    }
};

从源代码中可以看出_Function_handler有六种重载形式,以下对其进行分类说明:


template<typename _Functor>
inline _Functor& __callable_functor(_Functor& __f)
{ return __f; }

template<typename _Member, typename _Class>
inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* &__p)
{ return std::mem_fn(__p); }

template<typename _Member, typename _Class>
inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* const &__p)
{ return std::mem_fn(__p); }

template<typename _Member, typename _Class>
inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* volatile &__p)
{ return std::mem_fn(__p); }

template<typename _Member, typename _Class>
inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* const volatile &__p)
{ return std::mem_fn(__p); }

关于上面提到的std::reference_wrapper和std::mem_fn,大家如果可以不懂的话一定要看下面两篇文章,不然的话就像学英语不会英语单词一样,根本不可能看懂std::function的内容的

《C++11的std::ref、std::cref源码解析》
《C++11的std::mem_fn源码解析》

3.3、_Any_data解析

_Any_data位于libstdc++-v3\include\std\functional中


union _Nocopy_types
{
    void*       _M_object;
    const void* _M_const_object;
    void (*_M_function_pointer)();
    void (_Undefined_class::*_M_member_pointer)();
};

union _Any_data
{
    void*       _M_access()       { return &_M_pod_data[0]; }
    const void* _M_access() const { return &_M_pod_data[0]; }

    template<typename _Tp>
    _Tp& _M_access()
    { return *static_cast<_Tp*>(_M_access()); }

    template<typename _Tp>
    const _Tp& _M_access() const
    { return *static_cast<const _Tp*>(_M_access()); }

    _Nocopy_types _M_unused;
    char _M_pod_data[sizeof(_Nocopy_types)];
};

看std::_Function_base之前先看一个重要的联合体_Any_data,这个在前面出现很多次了,但是一直没有介绍一下它究竟是个什么东西,下面简单分析一下:

3.4、std::_Function_base解析

std::_Function_base的实现位于libstdc++-v3\include\std\functional中


class _Function_base
{
public:
    static const std::size_t _M_max_size = sizeof(_Nocopy_types);
    static const std::size_t _M_max_align = __alignof__(_Nocopy_types);

    template<typename _Functor>
    class _Base_manager
    {
    protected:
        static const bool __stored_locally =
            (__is_location_invariant<_Functor>::value
            && sizeof(_Functor) <= _M_max_size
            && __alignof__(_Functor) <= _M_max_align
            && (_M_max_align % __alignof__(_Functor) == 0));

        typedef integral_constant<bool, __stored_locally> _Local_storage;

        static _Functor* _M_get_pointer(const _Any_data& __source)
        {
            const _Functor* __ptr = __stored_locally? std::__addressof(__source._M_access<_Functor>()) : __source._M_access<_Functor*>();
            return const_cast<_Functor*>(__ptr);
        }

        static void _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
        {
            new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
        }

        static void _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
        {
            __dest._M_access<_Functor*>() = new _Functor(*__source._M_access<_Functor*>());
        }

        static void _M_destroy(_Any_data& __victim, true_type)
        {
            __victim._M_access<_Functor>().~_Functor();
        }

        static void _M_destroy(_Any_data& __victim, false_type)
        {
            delete __victim._M_access<_Functor*>();
        }

    public:
        static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
        {
            switch (__op)
            {
                case __get_functor_ptr:
                    __dest._M_access<_Functor*>() = _M_get_pointer(__source);
                    break;

                case __clone_functor:
                    _M_clone(__dest, __source, _Local_storage());
                    break;

                case __destroy_functor:
                    _M_destroy(__dest, _Local_storage());
                    break;
            }
            return false;
        }

        static void _M_init_functor(_Any_data& __functor, _Functor&& __f)
        { _M_init_functor(__functor, std::move(__f), _Local_storage()); }

        template<typename _Signature>
        static bool _M_not_empty_function(const function<_Signature>& __f)
        { return static_cast<bool>(__f); }

        template<typename _Tp>
        static bool _M_not_empty_function(_Tp* const& __fp)
        { return __fp; }

        template<typename _Class, typename _Tp>
        static bool _M_not_empty_function(_Tp _Class::* const& __mp)
        { return __mp; }

        template<typename _Tp>
        static bool _M_not_empty_function(const _Tp&)
        { return true; }

    private:
        static void _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
        { new (__functor._M_access()) _Functor(std::move(__f)); }

        static void _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
        { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
    };

    template<typename _Functor>
    class _Ref_manager : public _Base_manager<_Functor*>
    {
        typedef _Function_base::_Base_manager<_Functor*> _Base;

    public:
        static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
        {
            switch (__op)
            {
                case __get_functor_ptr:
                    __dest._M_access<_Functor*>() = *_Base::_M_get_pointer(__source);
                    return is_const<_Functor>::value;
                    break;

                default:
                    _Base::_M_manager(__dest, __source, __op);
            }
            return false;
        }

        static void _M_init_functor(_Any_data& __functor, reference_wrapper<_Functor> __f)
        {
            _Base::_M_init_functor(__functor, std::__addressof(__f.get()));
        }
    };

    _Function_base() : _M_manager(0) { }

    ~_Function_base()
    {
        if (_M_manager)
            _M_manager(_M_functor, _M_functor, __destroy_functor);
    }

    bool _M_empty() const { return !_M_manager; }

    typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, _Manager_operation);

    _Any_data     _M_functor;
    _Manager_type _M_manager;
};

从源代码中可以看出以下几点信息:

4、总结

本文先是简单介绍了std::function的用途(对C++中各种可调用实体进行封装),然后通过对源码进行详细分析,我们知道了std::function是如何实现对可调用实体进行封装的,源码内容会比较复杂,但是其中的设计思路是很值得我们学习借鉴的,尤其是与std::reference_wrapper和std::mem_fn配合的那部分代码更是精妙绝伦。
读者如果不清楚std::reference_wrapper和std::mem_fn的作用的话,是不可能完全看懂std::function的源代码的,所以这里再次建议大家先看完下面两篇文章再来学习std::function相关内容:

《C++11的std::ref、std::cref源码解析》
《C++11的std::mem_fn源码解析》

到此这篇关于浅谈C++11的std::function源码解析的文章就介绍到这了,更多相关C++11 std::function内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯