zoukankan      html  css  js  c++  java
  • VC的function类说明 -- 继续

    我在之前的随笔中介绍了function如何保存参数,如何实现调用相关知识。对于一个函数对象或者函数指针来说,应该很容易理解。不过对于如何在function中保存类的成员函数,这个还是值得一说的。

    还是按照之前的方式,通过boost的type_index,我们可以比较容易的知道function的父类是_Func_class。

    这里先看一段代码:

        template<class _Fx,
            class _Inv_res = typename _Mybase::template _Result_of_invoking_t<_Fx&>,
            class = typename _Mybase::template _Enable_if_returnable_t<_Inv_res> >
            function(_Fx _Func)
            {    // construct wrapper holding copy of _Func
            this->_Reset(_STD move(_Func));
            }

    这个是function的一个构造函数,其中的_Inv_res是这个构造函数能够使用的条件,条件的内容是_Mybase::_Result_of_invoking_t<_Fx&>可以获得一个类型。

    现在我们查看_Result_of_invoking_t定义的位置:

    protected:
        template<class _Fx>
            using _Result_of_invoking_t = result_of_t<_Fx(_Types...)>;

    上面是在_Func_class中的定义。下面给出类result_of_t的定义。

    template<class _Ty>
        using result_of_t = typename result_of<_Ty>::type;
    
    template<class _Void,
        class... _Types>
        struct _Result_of
        {    // selected when _Fty isn't callable with _Args
        };
    
    template<class... _Types>
        struct _Result_of<
            void_t<
                _Unique_tag_result_of,    // TRANSITION, C1XX
                decltype(_STD invoke(_STD declval<_Types>()...))>,
            _Types...>
        {    // selected when _Fty is callable with _Args
        typedef decltype(_STD invoke(_STD declval<_Types>()...)) type;
        };
    
    template<class _Fty>
        struct result_of
        {    // explain usage
        static_assert(_Always_false<_Fty>::value,
            "result_of<CallableType> is invalid; use "
            "result_of<CallableType(zero or more argument types)> instead.");
        };
    
    #define _RESULT_OF(CALL_OPT, X1, X2) 
    template<class _Fty, 
        class... _Args> 
        struct result_of<_Fty CALL_OPT (_Args...)> 
            : _Result_of<void, _Fty, _Args...> 
        {    /* template to determine result of call operation */ 
        };

    由上述代码可知,result_of的实现依赖于std::invoke函数的实现。

    我们再查看一下function函数的调用路径:

        _Ret operator()(_Types... _Args) const
            {    // call through stored object
            if (_Empty())
                _Xbad_function_call();
            return (_Getimpl()->_Do_call(_STD forward<_Types>(_Args)...));
            }

    上述是_Func_class的调用函数。

        virtual _Rx _Do_call(_Types&&... _Args)
            {    // call wrapped function
            return (_Invoke_ret(_Forced<_Rx>(), _Callee(),
                _STD forward<_Types>(_Args)...));
            }

    这个是_Func_impl的调用,也就是上面_Getimpl()->_Do_call的实现函数。下面,我们再查看一下_Invoke_ret的实现:

    template<class _Cv_void,
        class... _Valtys> inline
        void _Invoke_ret(_Forced<_Cv_void, true>, _Valtys&&... _Vals)
        {    // INVOKE, "implicitly" converted to void
        _STD invoke(_STD forward<_Valtys>(_Vals)...);
        }
    
    template<class _Rx,
        class... _Valtys> inline
        _Rx _Invoke_ret(_Forced<_Rx, false>, _Valtys&&... _Vals)
        {    // INVOKE, implicitly converted to _Rx
        return (_STD invoke(_STD forward<_Valtys>(_Vals)...));
        }
    
    template<class... _Valtys> inline
        auto _Invoke_ret(_Forced<_Unforced, false>, _Valtys&&... _Vals)
        -> decltype(_STD invoke(_STD forward<_Valtys>(_Vals)...))
        {    // INVOKE, unchanged
        return (_STD invoke(_STD forward<_Valtys>(_Vals)...));
        }

    由上面代码可见,无一例外,function的判断和实现都依赖于std::invoke的实现。那么std::invoke是如何实现的呢?

    template<class _Callable,
        class... _Types> inline
        auto invoke(_Callable&& _Obj, _Types&&... _Args)
        -> decltype(_Invoker<_Callable, _Types...>::_Call(
            _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...))
        {    // INVOKE a callable object
        return (_Invoker<_Callable, _Types...>::_Call(
            _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...));
        }

    在VS2015中,invoke的实现代码如上,可见invoke的实现依赖于_Invoker类。下面,我们查看一下_Invoker的实现:

    template<class _Callable,
        class... _Types>
        struct _Invoker;
    
    template<class _Callable>
        struct _Invoker<_Callable>
            : _Invoker_functor
        {    // zero arguments
        };
    
    template<class _Callable,
        class _Ty1,
        class... _Types2>
        struct _Invoker<_Callable, _Ty1, _Types2...>
            : _Invoker1<_Callable, _Ty1>
        {    // one or more arguments
        };

    可见,我们需要继续查看_Invoker1的实现:

    template<class _Callable,
        class _Ty1,
        class _Decayed = typename decay<_Callable>::type,
        bool _Is_pmf = is_member_function_pointer<_Decayed>::value,
        bool _Is_pmd = is_member_object_pointer<_Decayed>::value>
        struct _Invoker1;
    
    template<class _Callable,
        class _Ty1,
        class _Decayed>
        struct _Invoker1<_Callable, _Ty1, _Decayed, true, false>
            : _If<is_base_of<
                typename _Is_memfunptr<_Decayed>::_Class_type,
                typename decay<_Ty1>::type>::value,
            _Invoker_pmf_object,
            _Invoker_pmf_pointer>::type
        {    // pointer to member function
        };
    
    template<class _Callable,
        class _Ty1,
        class _Decayed>
        struct _Invoker1<_Callable, _Ty1, _Decayed, false, true>
            : _If<is_base_of<
                typename _Is_member_object_pointer<_Decayed>::_Class_type,
                typename decay<_Ty1>::type>::value,
            _Invoker_pmd_object,
            _Invoker_pmd_pointer>::type
        {    // pointer to member data
        };
    
    template<class _Callable,
        class _Ty1,
        class _Decayed>
        struct _Invoker1<_Callable, _Ty1, _Decayed, false, false>
            : _Invoker_functor
        {    // function object
        };

    以及实现_Invoker1的底层类:

    struct _Invoker_pmf_object
    {    // INVOKE a pointer to member function on an object
    template <class _Decayed, class _Ty1, class... _Types2>
    static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args)
    ->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 _Invoker_pmf_pointer
    {    // INVOKE a pointer to member function on a [smart] pointer
    template <class _Decayed, class _Ty1, class... _Types2>
    static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... Args2)
    ->decltype(((*std::forward<_Ty1>(_Arg1)).*_Pmf)(
        std::forward<_Types2>(_Arg2)...))
        {    // INVOKE a pointer to member function on a [smart] pointer
            return (((*std::forward<_Ty1>(_Arg1)).*_Pmf)(
            std::forward<_Types2>(_Arg2)...));
        }
    };
    
    struct _Invoker_pmd_object
    {    // INVOKE a pointer to member data on an object
    template<class _Decayed, class _Ty1>
    static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)
    ->decltype(std::forward<_Ty1>(_Arg1).*_Pmd)
    {    // INVOKE a pointer to member data on a [smart] pointer
        return (std::forward<_Ty1>(_Arg1).*_Pmd);
    }
        
    };
    
    struct _Invoker_pmd_pointer
    {    // INVOKE a pointer to member data on a [smart] pointer
    template <class _Decayed, class _Ty1>
    static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)
    ->decltype((*std::forward<_Ty1>(_Arg1)).*_Pmd)
    {    // INVOKE a pointer to member data on a [smart] pointer
        return ((*std::forward<_Ty1>(_Arg1)).*_Pmd);
    }
    };
    
    struct _Invoker_functor
    {    // INVOKE a function object
    template <class _Callable, class... _Types>
    static auto _Call(_Callable&& _Obj, _Types&&... _Args)
    ->decltype(std::forward<_Callable>(_Obj)(
        std::forward<_Types>(_Args)...))
        {    // INVOKE a function object
            return (std::forward<_Callable>(_Obj)(
                std::forward<_Types>(_Args)...));
        }
    };

    实现的过程,主要在于:bool _Is_pmf = is_member_function_pointer<_Decayed>::valuebool _Is_pmd = is_member_object_pointer<_Decayed>::value>两个判断语句,通过这个来实现SFINAE的语义,从而实现针对类型的特例化。为了说明上面两个判断才是重点,输入如下代码:

    class A
    {
    public:
        A(){}
    
        void printA() const
        {
            std::cout << "printA" << std::endl;
        }
    };
    
    void printB(A a)
    {
        std::cout << "printB" << std::endl;
    }
    
    int main()
    {
        std::_Invoker_pmf_object::_Call(&A::printA, A());
        std::_Invoker_pmf_pointer::_Call(&A::printA, &A());
        std::_Invoker_functor::_Call(printB, A());
        
        return 0;
    }

    查看打印结果。由于_Invoker_pmf_object_Invoker_pmf_pointer_Invoker_functor的实现本来很简单,所以invoke调用的重点在于上述判断语句。这里就解释到此,时间仓促,希望见谅。

  • 相关阅读:
    LIKE谓词
    [C#网络编程系列]专题一:网络协议简介
    (zz)Sql Server 2005中的架构(Schema)、用户(User)、角色(Role)和登录(Login)(三)
    zz让你成功的九个心理定律
    zz给 VSTO 插件、文档传送参数
    重构笔记
    (zz)Sql Server 2005中的架构(Schema)、用户(User)、角色(Role)和登录(Login)(二)
    zzVSTO 先瘦身再发布:客户端配置文件
    zz将 VSTO 插件部署给所有用户
    (zz)Sql Server 2005中的架构(Schema)、用户(User)、角色(Role)和登录(Login)(一)
  • 原文地址:https://www.cnblogs.com/albizzia/p/9074913.html
Copyright © 2011-2022 走看看