VC编程之VC的function类说明 -- 继续
小标 2018-09-04 来源 : 阅读 1518 评论 0

摘要:本文主要向大家介绍了VC编程之VC的function类说明 -- 继续,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

本文主要向大家介绍了VC编程之VC的function类说明 -- 继续,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

我在之前的随笔中介绍了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>::value和bool _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调用的重点在于上述判断语句。这里就解释到此,时间仓促,希望见谅。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程