std::function 学习笔记(3)

下面是我的std::function的阅读笔记:


// CLASS TEMPLATE function
template 
class function : public _Get_function_impl<_Fty>::type { // wrapper for callable objects // 注意这里,继承的是_Get_function_impl<_Fty>::type ,即_Func_class<_Ret, _Types...>;
private:
    using _Mybase = typename _Get_function_impl<_Fty>::type;

public:
    function() noexcept {}

    function(nullptr_t) noexcept {}

    function(const function& _Right) {
        this->_Reset_copy(_Right);
    }

    template >
    function(_Fx _Func) {
        this->_Reset(_STD move(_Func));
    }

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template 
    function(allocator_arg_t, const _Alloc&) noexcept {}

    template 
    function(allocator_arg_t, const _Alloc&, nullptr_t) noexcept {}

    template 
    function(allocator_arg_t, const _Alloc& _Ax, const function& _Right) {
        this->_Reset_alloc(_Right, _Ax);
    }

    template >
    function(allocator_arg_t, const _Alloc& _Ax, _Fx _Func) {
        this->_Reset_alloc(_STD move(_Func), _Ax);
    }
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT

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

    function(function&& _Right) noexcept {
        this->_Reset_move(_STD move(_Right));
    }

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template 
    function(allocator_arg_t, const _Alloc& _Al, function&& _Right) {
        this->_Reset_alloc(_STD move(_Right), _Al);
    }
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT

    function& operator=(function&& _Right) noexcept /* strengthened */ {
        if (this != _STD addressof(_Right)) {
            this->_Tidy();
            this->_Reset_move(_STD move(_Right));
        }
        return *this;
    }

    template &, function>>
    function& operator=(_Fx&& _Func) {
        function(_STD forward<_Fx>(_Func)).swap(*this);
        return *this;
    }

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template 
    void assign(_Fx&& _Func, const _Alloc& _Ax) {
        function(allocator_arg, _Ax, _STD forward<_Fx>(_Func)).swap(*this);
    }
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT

    function& operator=(nullptr_t) noexcept {
        this->_Tidy();
        return *this;
    }

    template 
    function& operator=(reference_wrapper<_Fx> _Func) noexcept {
        this->_Tidy();
        this->_Reset(_Func);
        return *this;
    }

    void swap(function& _Right) noexcept {
        this->_Swap(_Right);
    }

    explicit operator bool() const noexcept {
        return !this->_Empty();
    }

#if _HAS_STATIC_RTTI
    _NODISCARD const type_info& target_type() const noexcept {
        return this->_Target_type();
    }

    template 
    _NODISCARD _Fx* target() noexcept {
        return reinterpret_cast<_Fx*>(const_cast(this->_Target(typeid(_Fx))));
    }

    template 
    _NODISCARD const _Fx* target() const noexcept {
        return reinterpret_cast(this->_Target(typeid(_Fx)));
    }
#else // _HAS_STATIC_RTTI
    const type_info& target_type() const noexcept = delete; // requires static RTTI

    template 
    _Fx* target() noexcept = delete; // requires static RTTI

    template 
    const _Fx* target() const noexcept = delete; // requires static RTTI
#endif // _HAS_STATIC_RTTI
};

接下来看其基类实现:


// CLASS TEMPLATE _Func_class --------也就是std::function的基类
template 
class _Func_class : public _Arg_types<_Types...> {
public:
    using result_type = _Ret;

    using _Ptrt = _Func_base<_Ret, _Types...>;// 这个基类定义了一系列的虚函数

    _Func_class() noexcept {
        _Set(nullptr);
    }

    _Ret operator()(_Types... _Args) const {
        if (_Empty()) {
            _Xbad_function_call();
        }
        const auto _Impl = _Getimpl();
        return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
    }

    ~_Func_class() noexcept {
        _Tidy();
    }

protected:
    template 
    using _Enable_if_callable_t =
        enable_if_t, _Function>>, _Is_invocable_r<_Ret, _Fx, _Types...>>>;

    bool _Empty() const noexcept {
        return !_Getimpl();
    }

    void _Reset_copy(const _Func_class& _Right) { // copy _Right's stored object
        if (!_Right._Empty()) {
            _Set(_Right._Getimpl()->_Copy(&_Mystorage));
        }
    }

    void _Reset_move(_Func_class&& _Right) noexcept { // move _Right's stored object
        if (!_Right._Empty()) {
            if (_Right._Local()) { // move and tidy
                _Set(_Right._Getimpl()->_Move(&_Mystorage));
                _Right._Tidy();
            } else { // steal from _Right
                _Set(_Right._Getimpl());
                _Right._Set(nullptr);
            }
        }
    }

    template 
    void _Reset(_Fx&& _Val) { // store copy of _Val
        if (!_Test_callable(_Val)) { // null member pointer/function pointer/std::function
            return; // already empty
        }
/*
// FUNCTION TEMPLATE _Global_new
template 
_Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection
    struct _Guard_type {
        void* _Result;
        ~_Guard_type() {
            if (_Result) {
                _Deallocate<_New_alignof<_Ty>>(_Result, sizeof(_Ty));
            }
        }
    };

    _Guard_type _Guard{_Allocate<_New_alignof<_Ty>>(sizeof(_Ty))};
    ::new (_Guard._Result) _Ty(_STD forward<_Types>(_Args)...);
    return static_cast<_Ty*>(_STD exchange(_Guard._Result, nullptr));// 这种写法,确保了异常安全,太牛皮了
}
*/
        using _Impl = _Func_impl_no_alloc, _Ret, _Types...>;// 注意下面的_Set 对应的参数类型为接口指针,而这里是模板类,看模板类的声明可以发现其继承了_Func_base<_Rx, _Types...>
        if
            _CONSTEXPR_IF(_Is_large<_Impl>) {
                // dynamically allocate _Val
                _Set(_Global_new<_Impl>(_STD forward<_Fx>(_Val)));// 全局申请操作
            }
        else {
            // store _Val in-situ
            _Set(::new (static_cast(&_Mystorage)) _Impl(_STD forward<_Fx>(_Val)));// placement new 操作
        }
    }

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template 
    void _Reset_alloc(_Fx&& _Val, const _Alloc& _Ax) { // store copy of _Val with allocator
        if (!_Test_callable(_Val)) { // null member pointer/function pointer/std::function
            return; // already empty
        }

        using _Myimpl = _Func_impl, _Alloc, _Ret, _Types...>;
        if
            _CONSTEXPR_IF(_Is_large<_Myimpl>) {
                // dynamically allocate _Val
                using _Alimpl = _Rebind_alloc_t<_Alloc, _Myimpl>;
                _Alimpl _Al(_Ax);
                _Alloc_construct_ptr<_Alimpl> _Constructor{_Al};
                _Constructor._Allocate();
                _Construct_in_place(*_Constructor._Ptr, _STD forward<_Fx>(_Val), _Ax);
                _Set(_Unfancy(_Constructor._Release()));
            }
        else {
            // store _Val in-situ
            const auto _Ptr = reinterpret_cast<_Myimpl*>(&_Mystorage);
            _Construct_in_place(*_Ptr, _STD forward<_Fx>(_Val), _Ax);
            _Set(_Ptr);
        }
    }
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT

    void _Tidy() noexcept {
        if (!_Empty()) { // destroy callable object and maybe delete it
            _Getimpl()->_Delete_this(!_Local());
            _Set(nullptr);
        }
    }

    void _Swap(_Func_class& _Right) noexcept { // swap contents with contents of _Right
        if (!_Local() && !_Right._Local()) { // just swap pointers
            _Ptrt* _Temp = _Getimpl();
            _Set(_Right._Getimpl());
            _Right._Set(_Temp);
        } else { // do three-way move
            _Func_class _Temp;
            _Temp._Reset_move(_STD move(*this));
            _Reset_move(_STD move(_Right));
            _Right._Reset_move(_STD move(_Temp));
        }
    }

#if _HAS_STATIC_RTTI
    const type_info& _Target_type() const noexcept {
        return _Getimpl() ? _Getimpl()->_Target_type() : typeid(void);
    }

    const void* _Target(const type_info& _Info) const noexcept {
        return _Getimpl() ? _Getimpl()->_Target(_Info) : nullptr;
    }
#endif // _HAS_STATIC_RTTI

private:
    bool _Local() const noexcept { // test for locally stored copy of object
        return _Getimpl() == static_cast(&_Mystorage);// 判断是否是本地存储,如果内部存储的空间地址就是_Mystorage的地址了,肯定就是本地的了
    }

    union _Storage { // storage for small objects (basic_string is small)
        max_align_t _Dummy1; // for maximum alignment
        char _Dummy2[_Space_size]; // to permit aliasing
        _Ptrt* _Ptrs[_Small_object_num_ptrs]; // _Ptrs[_Small_object_num_ptrs - 1] is reserved
    };

    _Storage _Mystorage;// 公共的存储空间,如果大小比较小,就用这个部分直接存储数据,否则,就需要动态申请内存了
    enum { _EEN_IMPL = _Small_object_num_ptrs - 1 }; // helper for expression evaluator
    _Ptrt* _Getimpl() const noexcept { // get pointer to object
        return _Mystorage._Ptrs[_Small_object_num_ptrs - 1];// 对应下面的_Set函数,这里有一个读取的动作
    }

    void _Set(_Ptrt* _Ptr) noexcept { // store pointer to object
        _Mystorage._Ptrs[_Small_object_num_ptrs - 1] = _Ptr;// 最后一个位置,需要存储我们的接口指针,因此,在计算是否超过存储空间大小的时候,需要去掉这一块的大小
    }
};

其接口定义和实现类为:

接口定义
// CLASS TEMPLATE _Func_base
template 
class __declspec(novtable) _Func_base { // abstract base for implementation types
public:
    virtual _Func_base* _Copy(void*) const                 = 0;
    virtual _Func_base* _Move(void*) noexcept              = 0;
    virtual _Rx _Do_call(_Types&&...)                      = 0;
    virtual const type_info& _Target_type() const noexcept = 0;
    virtual void _Delete_this(bool) noexcept               = 0;

#if _HAS_STATIC_RTTI
    const void* _Target(const type_info& _Info) const noexcept {
        return _Target_type() == _Info ? _Get() : nullptr;
    }
#endif // _HAS_STATIC_RTTI

    _Func_base()                  = default;
    _Func_base(const _Func_base&) = delete;
    _Func_base& operator=(const _Func_base&) = delete;
    // dtor non-virtual due to _Delete_this()

private:
    virtual const void* _Get() const noexcept = 0;
};

实现:
// CLASS TEMPLATE _Func_impl_no_alloc
template 
class _Func_impl_no_alloc final : public _Func_base<_Rx, _Types...> {
    // derived class for specific implementation types that don't use allocators
public:
    using _Mybase       = _Func_base<_Rx, _Types...>;
    using _Nothrow_move = is_nothrow_move_constructible<_Callable>;

    template >>>
    explicit _Func_impl_no_alloc(_Other&& _Val) : _Callee(_STD forward<_Other>(_Val)) {}

    // dtor non-virtual due to _Delete_this()

private:
    virtual _Mybase* _Copy(void* _Where) const override {
        if
            _CONSTEXPR_IF(_Is_large<_Func_impl_no_alloc>) {// 构造的时候,如果太大了,就需要动态申请内存了
                (void) _Where;
                return _Global_new<_Func_impl_no_alloc>(_Callee);
            }
        else {
            return ::new (_Where) _Func_impl_no_alloc(_Callee);// 否则,需要使用placement new 操作
        }
    }

    virtual _Mybase* _Move(void* _Where) noexcept override {
        if
            _CONSTEXPR_IF(_Is_large<_Func_impl_no_alloc>) {
                (void) _Where;
                return nullptr;
            }
        else {
            return ::new (_Where) _Func_impl_no_alloc(_STD move(_Callee));
        }
    }

    virtual _Rx _Do_call(_Types&&... _Args) override { // call wrapped function
        return _Invoker_ret<_Rx>::_Call(_Callee, _STD forward<_Types>(_Args)...);
    }

    virtual const type_info& _Target_type() const noexcept override {
#if _HAS_STATIC_RTTI
        return typeid(_Callable);
#else // _HAS_STATIC_RTTI
        return typeid(void);
#endif // _HAS_STATIC_RTTI
    }

    virtual const void* _Get() const noexcept override {
        return _STD addressof(_Callee);
    }

    virtual void _Delete_this(bool _Dealloc) noexcept override { // destroy self
        this->~_Func_impl_no_alloc();
        if (_Dealloc) {
            _Deallocate(this, sizeof(_Func_impl_no_alloc));
        }
    }

    _Callable _Callee;
};

既然是函数对象,那么其调用过程如何呢?

接口定义里面,定义了如下接口:

virtual _Rx _Do_call(_Types&&...)                      = 0;

另外我们找到了重载operator()的地方:


// CLASS TEMPLATE _Func_class --------也就是std::function的基类
template 
class _Func_class : public _Arg_types<_Types...> {
public:
    using result_type = _Ret;

    using _Ptrt = _Func_base<_Ret, _Types...>;// 这个基类定义了一系列的虚函数

    _Func_class() noexcept {
        _Set(nullptr);
    }

    _Ret operator()(_Types... _Args) const {// _Func_class 重载了operator(),以进行函数调用
        if (_Empty()) {
            _Xbad_function_call();
        }
        const auto _Impl = _Getimpl();
        return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
    }

_Func_impl_no_alloc 中实现如下:

    virtual _Rx _Do_call(_Types&&... _Args) override { // call wrapped function
        return _Invoker_ret<_Rx>::_Call(_Callee, _STD forward<_Types>(_Args)...);
    }

其中用了一些奇淫技巧,如下:

 

std::function 学习笔记(3)_第1张图片

最终会跑到这里的宏定义里面:

#define _IMPLEMENT_INVOKE(NAME_PREFIX, CONSTEXPR)                                                                      \
    /* FUNCTION TEMPLATE invoke */                                                                                     \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmf_object) { /* INVOKE a pointer to member function on an object */          \
        template                                                         \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept(                        \
            noexcept((_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...)))                             \
            -> decltype((_STD forward<_Ty1>(_Arg1).*_Pmf)(                                                             \
                _STD forward<_Types2>(_Args2)...)) { /* INVOKE a pointer to member function on an object */            \
            return (_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...);                                \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(                                                                                                    \
        NAME_PREFIX, _Invoker_pmf_refwrap) { /* INVOKE a pointer to member function on a reference_wrapper */          \
        template                                                         \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept(                        \
            noexcept((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(_Args2)...)))                       \
            -> decltype((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(                                                       \
                _STD forward<_Types2>(_Args2)...)) { /* INVOKE a pointer to member function on a reference_wrapper */  \
            return (_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(_Args2)...);                          \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmf_pointer) { /* INVOKE a pointer to member function on a [smart] pointer */ \
        template                                                         \
        static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept(                        \
            noexcept(((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(_Args2)...)))                          \
            -> decltype(((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(                                                          \
                _STD forward<_Types2>(_Args2)...)) { /* INVOKE a pointer to member function on a [smart] pointer */    \
            return ((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(_Args2)...);                             \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_object) { /* INVOKE a pointer to member data on an object */              \
        template                                                                           \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept(noexcept(_STD forward<_Ty1>(_Arg1).*_Pmd))   \
            -> decltype(_STD forward<_Ty1>(_Arg1).*_Pmd) { /* INVOKE a pointer to member data on an object */          \
            return _STD forward<_Ty1>(_Arg1).*_Pmd;                                                                    \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap) { /* INVOKE a pointer to member data on a reference_wrapper */   \
        template                                                                           \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept(                                             \
            noexcept(_STD forward<_Ty1>(_Arg1).get().*_Pmd))                                                           \
            -> decltype(                                                                                               \
                _STD forward<_Ty1>(_Arg1).get().*_Pmd) { /* INVOKE a pointer to member data on a reference_wrapper */  \
            return _STD forward<_Ty1>(_Arg1).get().*_Pmd;                                                              \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_pmd_pointer) { /* INVOKE a pointer to member data on a [smart] pointer */     \
        template                                                                           \
        static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept(                                             \
            noexcept((*_STD forward<_Ty1>(_Arg1)).*_Pmd))                                                              \
            -> decltype(                                                                                               \
                (*_STD forward<_Ty1>(_Arg1)).*_Pmd) { /* INVOKE a pointer to member data on a [smart] pointer */       \
            return (*_STD forward<_Ty1>(_Arg1)).*_Pmd;                                                                 \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    struct _CONCAT(NAME_PREFIX, _Invoker_functor) { /* INVOKE a function object */                                     \
        template                                                                     \
        static CONSTEXPR auto _Call(_Callable&& _Obj, _Types&&... _Args) noexcept(                                     \
            noexcept(_STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...)))                                   \
            -> decltype(                                                                                               \
                _STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...)) { /* INVOKE a function object */        \
            return _STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...);                                      \
        }                                                                                                              \
    };                                                                                                                 \
                                                                                                                       \
    template ,                          \
        bool _Is_pmf = is_member_function_pointer_v<_Removed_cvref>,                                                   \
        bool _Is_pmd = is_member_object_pointer_v<_Removed_cvref>>                                                     \
    struct _CONCAT(NAME_PREFIX, _Invoker1);                                                                            \
                                                                                                                       \
    template                                                        \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, true, false>                               \
        : conditional_t::_Class_type, remove_reference_t<_Ty1>>,   \
              _CONCAT(NAME_PREFIX, _Invoker_pmf_object),                                                               \
              conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>,                            \
                  _CONCAT(NAME_PREFIX, _Invoker_pmf_refwrap),                                                          \
                  _CONCAT(NAME_PREFIX, _Invoker_pmf_pointer)>> { /* pointer to member function */                      \
    };                                                                                                                 \
                                                                                                                       \
    template                                                        \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, true>                               \
        : conditional_t<                                                                                               \
              is_base_of_v::_Class_type, remove_reference_t<_Ty1>>, \
              _CONCAT(NAME_PREFIX, _Invoker_pmd_object),                                                               \
              conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>,                            \
                  _CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap),                                                          \
                  _CONCAT(NAME_PREFIX, _Invoker_pmd_pointer)>> { /* pointer to member data */                          \
    };                                                                                                                 \
                                                                                                                       \
    template                                                        \
    struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, false>                              \
        : _CONCAT(NAME_PREFIX, _Invoker_functor) { /* function object */                                               \
    };                                                                                                                 \
                                                                                                                       \
    template                                                                         \
    struct _CONCAT(NAME_PREFIX, _Invoker);                                                                             \
                                                                                                                       \
    template                                                                                          \
    struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable> : _CONCAT(NAME_PREFIX, _Invoker_functor) { /* zero arguments */   \
    };                                                                                                                 \
                                                                                                                       \
    template                                                            \
    struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Ty1, _Types2...>                                                 \
        : _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1> { /* one or more arguments */                               \
    };                                                                                                                 \
                                                                                                                       \
    template                                                                         \
    CONSTEXPR auto _CONCAT(NAME_PREFIX, invoke)(_Callable && _Obj, _Types && ... _Args) noexcept(                      \
        noexcept(_CONCAT(NAME_PREFIX, _Invoker) < _Callable,                                                           \
            _Types... > ::_Call(_STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)))                       \
        ->decltype(_CONCAT(NAME_PREFIX, _Invoker) < _Callable,                                                         \
            _Types... > ::_Call(                                                                                       \
                _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)) { /* INVOKE a callable object */       \
        return _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Types...>::_Call(                                            \
            _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...);                                            \
    }

_IMPLEMENT_INVOKE(_EMPTY_ARGUMENT, inline)

这个可读性就太差了,既然微软提供的functional 中的这部分功能,就是利用了template 的能力,理想情况下,我们是可以通过自己的封装来实现一个建议版本的functional的,看时间和精力吧,可以尝试实现一下。

你可能感兴趣的:(学习笔记)