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

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

这里先看一段代码:

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

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

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

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

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

  1. template<class _Ty>
  2. using result_of_t = typename result_of<_Ty>::type;
  3.  
  4. template<class _Void,
  5. class... _Types>
  6. struct _Result_of
  7. { // selected when _Fty isn't callable with _Args
  8. };
  9.  
  10. template<class... _Types>
  11. struct _Result_of<
  12. void_t<
  13. _Unique_tag_result_of, // TRANSITION, C1XX
  14. decltype(_STD invoke(_STD declval<_Types>()...))>,
  15. _Types...>
  16. { // selected when _Fty is callable with _Args
  17. typedef decltype(_STD invoke(_STD declval<_Types>()...)) type;
  18. };
  19.  
  20. template<class _Fty>
  21. struct result_of
  22. { // explain usage
  23. static_assert(_Always_false<_Fty>::value,
  24. "result_of<CallableType> is invalid; use "
  25. "result_of<CallableType(zero or more argument types)> instead.");
  26. };
  27.  
  28. #define _RESULT_OF(CALL_OPT, X1, X2) \
  29. template<class _Fty, \
  30. class... _Args> \
  31. struct result_of<_Fty CALL_OPT (_Args...)> \
  32. : _Result_of<void, _Fty, _Args...> \
  33. { /* template to determine result of call operation */ \
  34. };

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

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

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

上述是_Func_class的调用函数。

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

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

  1. template<class _Cv_void,
  2. class... _Valtys> inline
  3. void _Invoke_ret(_Forced<_Cv_void, true>, _Valtys&&... _Vals)
  4. { // INVOKE, "implicitly" converted to void
  5. _STD invoke(_STD forward<_Valtys>(_Vals)...);
  6. }
  7.  
  8. template<class _Rx,
  9. class... _Valtys> inline
  10. _Rx _Invoke_ret(_Forced<_Rx, false>, _Valtys&&... _Vals)
  11. { // INVOKE, implicitly converted to _Rx
  12. return (_STD invoke(_STD forward<_Valtys>(_Vals)...));
  13. }
  14.  
  15. template<class... _Valtys> inline
  16. auto _Invoke_ret(_Forced<_Unforced, false>, _Valtys&&... _Vals)
  17. -> decltype(_STD invoke(_STD forward<_Valtys>(_Vals)...))
  18. { // INVOKE, unchanged
  19. return (_STD invoke(_STD forward<_Valtys>(_Vals)...));
  20. }

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

  1. template<class _Callable,
  2. class... _Types> inline
  3. auto invoke(_Callable&& _Obj, _Types&&... _Args)
  4. -> decltype(_Invoker<_Callable, _Types...>::_Call(
  5. _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...))
  6. { // INVOKE a callable object
  7. return (_Invoker<_Callable, _Types...>::_Call(
  8. _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...));
  9. }

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

  1. template<class _Callable,
  2. class... _Types>
  3. struct _Invoker;
  4.  
  5. template<class _Callable>
  6. struct _Invoker<_Callable>
  7. : _Invoker_functor
  8. { // zero arguments
  9. };
  10.  
  11. template<class _Callable,
  12. class _Ty1,
  13. class... _Types2>
  14. struct _Invoker<_Callable, _Ty1, _Types2...>
  15. : _Invoker1<_Callable, _Ty1>
  16. { // one or more arguments
  17. };

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

  1. template<class _Callable,
  2. class _Ty1,
  3. class _Decayed = typename decay<_Callable>::type,
  4. bool _Is_pmf = is_member_function_pointer<_Decayed>::value,
  5. bool _Is_pmd = is_member_object_pointer<_Decayed>::value>
  6. struct _Invoker1;
  7.  
  8. template<class _Callable,
  9. class _Ty1,
  10. class _Decayed>
  11. struct _Invoker1<_Callable, _Ty1, _Decayed, true, false>
  12. : _If<is_base_of<
  13. typename _Is_memfunptr<_Decayed>::_Class_type,
  14. typename decay<_Ty1>::type>::value,
  15. _Invoker_pmf_object,
  16. _Invoker_pmf_pointer>::type
  17. { // pointer to member function
  18. };
  19.  
  20. template<class _Callable,
  21. class _Ty1,
  22. class _Decayed>
  23. struct _Invoker1<_Callable, _Ty1, _Decayed, false, true>
  24. : _If<is_base_of<
  25. typename _Is_member_object_pointer<_Decayed>::_Class_type,
  26. typename decay<_Ty1>::type>::value,
  27. _Invoker_pmd_object,
  28. _Invoker_pmd_pointer>::type
  29. { // pointer to member data
  30. };
  31.  
  32. template<class _Callable,
  33. class _Ty1,
  34. class _Decayed>
  35. struct _Invoker1<_Callable, _Ty1, _Decayed, false, false>
  36. : _Invoker_functor
  37. { // function object
  38. };

以及实现_Invoker1的底层类:

  1. struct _Invoker_pmf_object
  2. { // INVOKE a pointer to member function on an object
  3. template <class _Decayed, class _Ty1, class... _Types2>
  4. static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args)
  5. ->decltype((std::forward<_Ty1>(_Arg1).*_Pmf)(
  6. std::forward<_Types2>(_Args2)...))
  7. { // INVOKE a pointer to member function on an object
  8. return ((_STD forward<_Ty1>(_Arg1).*_Pmf)(
  9. std::forward<_Types2>(_Args2)...
  10. ));
  11. }
  12. };
  13.  
  14. struct _Invoker_pmf_pointer
  15. { // INVOKE a pointer to member function on a [smart] pointer
  16. template <class _Decayed, class _Ty1, class... _Types2>
  17. static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... Args2)
  18. ->decltype(((*std::forward<_Ty1>(_Arg1)).*_Pmf)(
  19. std::forward<_Types2>(_Arg2)...))
  20. { // INVOKE a pointer to member function on a [smart] pointer
  21. return (((*std::forward<_Ty1>(_Arg1)).*_Pmf)(
  22. std::forward<_Types2>(_Arg2)...));
  23. }
  24. };
  25.  
  26. struct _Invoker_pmd_object
  27. { // INVOKE a pointer to member data on an object
  28. template<class _Decayed, class _Ty1>
  29. static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)
  30. ->decltype(std::forward<_Ty1>(_Arg1).*_Pmd)
  31. { // INVOKE a pointer to member data on a [smart] pointer
  32. return (std::forward<_Ty1>(_Arg1).*_Pmd);
  33. }
  34.  
  35. };
  36.  
  37. struct _Invoker_pmd_pointer
  38. { // INVOKE a pointer to member data on a [smart] pointer
  39. template <class _Decayed, class _Ty1>
  40. static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1)
  41. ->decltype((*std::forward<_Ty1>(_Arg1)).*_Pmd)
  42. { // INVOKE a pointer to member data on a [smart] pointer
  43. return ((*std::forward<_Ty1>(_Arg1)).*_Pmd);
  44. }
  45. };
  46.  
  47. struct _Invoker_functor
  48. { // INVOKE a function object
  49. template <class _Callable, class... _Types>
  50. static auto _Call(_Callable&& _Obj, _Types&&... _Args)
  51. ->decltype(std::forward<_Callable>(_Obj)(
  52. std::forward<_Types>(_Args)...))
  53. { // INVOKE a function object
  54. return (std::forward<_Callable>(_Obj)(
  55. std::forward<_Types>(_Args)...));
  56. }
  57. };

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

  1. class A
  2. {
  3. public:
  4. A(){}
  5.  
  6. void printA() const
  7. {
  8. std::cout << "printA" << std::endl;
  9. }
  10. };
  11.  
  12. void printB(A a)
  13. {
  14. std::cout << "printB" << std::endl;
  15. }
  16.  
  17. int main()
  18. {
  19. std::_Invoker_pmf_object::_Call(&A::printA, A());
  20. std::_Invoker_pmf_pointer::_Call(&A::printA, &A());
  21. std::_Invoker_functor::_Call(printB, A());
  22.  
  23. return ;
  24. }

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

VC的function类说明 -- 继续的更多相关文章

  1. VC中function函数解析

    C++标准库是日常应用中非常重要的库,我们会用到C++标准库的很多组件,C++标准库的作用,不单单是一种可以很方便使用的组件,也是我们学习很多实现技巧的重要宝库.我一直对C++很多组件的实现拥有比较强 ...

  2. VC++导入导出类

    一.导出类 VC++中导出类很简单,下面列出了两个等价的方法: 方法1: class __declspec(dllexport) CTest { public: int        m_nValue ...

  3. VC++中的类的内存分布(上)

    0.序 目前正在学习C++中,对于C++的类及其类的实现原理也挺感兴趣.于是打算通过观察类在内存中的分布更好地理解类的实现.因为其实类的分布是由编译器决定的,而本次试验使用的编译器为VS2015 RC ...

  4. VC++中的类的内存分布(上)(通过强制转换,观察地址,以及地址里的值来判断)

    0.序 目前正在学习C++中,对于C++的类及其类的实现原理也挺感兴趣.于是打算通过观察类在内存中的分布更好地理解类的实现.因为其实类的分布是由编译器决定的,而本次试验使用的编译器为VS2015 RC ...

  5. JavaScript学习总结(十五)——Function类

    在JavaScript中,函数其实是对象,每个函数都是Function类的实例,既然函数对象,那么就具有自己的属性和方法,因此,函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. 一.函数的 ...

  6. js面向对象设计之function类

    本文仅探讨如何合理的使用 function 在 javascript中实现一个面向对象设计的类.总所周知,javascript 并不能实现一个真正意义上的类,比如 protect 比如 函数重载.下面 ...

  7. JavaScript语言精粹--Function,类,this,对象

    1.类与对象 在JS中,创建对象(Create Object)并不完全是我们时常说的创建类对象,JS中的对象强调的是一种复合类型,JS中创建对象及对对象的访问是极其灵活的. JS对象是一种复合类型,它 ...

  8. 【C++对象模型】使用gcc、clang和VC++显示C++类的内存布局

    引言 各种C++实现对C++类/对象的内存布局可能有所不同,包括数据成员的顺序.虚函数表(virtual table: vtbl)的结构.继承关系的处理等.了解C++类/对象的布局,对于理解C++各种 ...

  9. 钩子函数 Function类

    Function 为 com.google.common.base包下接口类: public interface Function<F, T> { @Nullable T apply(@N ...

随机推荐

  1. 实验吧—Web——WP之 貌似有点难

    其实这道题并不难,只要会看一点PHP语句,会用BP抓包,改包就好了 打开解题链接: 提示有:PHP代码审计,并且有一个:View the source code 的按钮 我们点击打开 打开后发现是一段 ...

  2. 实验吧—隐写术——WP之 Fair-Play

    首先,我们读题发现题目是Playfair​,其实我也不知道这是什么,那么就百度一下啊 Playfair解密算法: 首先将密钥填写在一个5*5的矩阵中(去Q留Z),矩阵中其它未用到的字母按顺序填在矩阵剩 ...

  3. ios 上浏览器返回上一页不会刷新页面问题,页面初始化的方法不执行

    https://blog.csdn.net/yang450712123/article/details/79276102 https://blog.csdn.net/Chengbin_Huang/ar ...

  4. day16 Hbase day17

    这个HBase学习了第二遍也不是太透彻PS:启动Hbase之前先启动Zookeeper.HDFS.yarn 1. hbase简介(是基于HDFS.相当于是一个缓存层) 1.1. 什么是hbase(列式 ...

  5. dive 方便的观察容器各层信息的工具

      dive 是一个方便的观察容器各层信息的工具,同时也集成了容器构建命令,方便我们在构建容器 镜像的同时查询镜像各层的变动信息 安装 mac 系统,可以按照自己的系统选择安装方式 wget http ...

  6. TypeScript 与 es6 写法的区别

    import 方式 ts 默认对于 commonjs 的模块是这样加载的:import * as React from 'react'; es6:import React from 'react'; ...

  7. 将 vue 挂在 window 对象上,实现能调用 elementUI 的组件

    html 部分: <div id="sample"> </div> js 部分(将js代码放在 body 的 onload事件中: <body onl ...

  8. mysql 不允许分组的问题

    异常信息:this is incompatible with sql_mode=only_full_group_by 解决办法: 找到  my.cnf  find / -name my.cnf 然后在 ...

  9.  WPF 控件总结

    内容控件:1.Button:当Button.IsCancel="True"时,点击按钮,对话框关闭.当Button.IsDefault="True",按回车触发 ...

  10. Spring 中PageHelper分页插件使用

    1.增加pagehelper <!-- mybatis pager --> <dependency> <groupId>com.github.pagehelper& ...