• 【C++ 高级编程 | 18】std::invoke


      1 #include <iostream>
      2 #include <functional>
      3 // ========================================================================
      4 // 第三步
      5 // 调用普通函数的版本
      6 struct _InvokeFunction
      7 {
      8     template <typename _Callable, typename... _Types>
      9     static auto _Call(_Callable &&obj, _Types &&...argv)
     10     {
     11         return obj(std::forward<_Types>(argv)...);
     12     }
     13 };
     14 // 调用成员函数版本
     15 struct _InvokeMemFunc
     16 {
     17     template <typename _Callable, typename _Obj, typename... _Types>
     18     static auto _Call(_Callable &&fn, _Obj &&obj, _Types &&...argv) -> decltype((obj->*fn)(std::forward<_Types>(argv)...))
     19     {
     20         return (obj->*fn)(std::forward<_Types>(argv)...);
     21     }
     22     // 这里和stl当中方法不一样,这里采用使用SFINAE技术
     23     // 编译器会自动选择两者当中可调用的版本
     24     template <typename _Callable, typename _Obj, typename... _Types>
     25     static auto _Call(_Callable &&fn, _Obj &&obj, _Types &&...argv) -> decltype((obj.*fn)(std::forward<_Types>(argv)...))
     26     {
     27         return (obj.*fn)(std::forward<_Types>(argv)...);
     28     }
     29 };
     30 // 调用成员变量
     31 struct _InvokeMemObj
     32 {
     33     template <typename _Callable, typename _Obj>
     34     static auto _Call(_Callable &&fn, _Obj &&obj) -> decltype((obj->*fn))
     35     {
     36         return (obj->*fn);
     37     }
     38     template <typename _Callable, typename _Obj>
     39     static auto _Call(_Callable &&fn, _Obj &&obj) -> decltype((obj.*fn))
     40     {
     41         return (obj.*fn);
     42     }
     43 };
     44 // =========================================================================
     45 // 第二步
     46 // 第二层,筛选多参数普通函数,成员函数,数据成员
     47 // 暂时依赖标准库的萃取技术
     48 template <typename _Callable,
     49                     typename _FirstTy,
     50                     typename _Decayed = typename std::decay<_Callable>::type,
     51                     bool _Is_MemFun = std::is_member_function_pointer<_Decayed>::value,
     52                     bool _Is_MemObj = std::is_member_object_pointer<_Decayed>::value>
     53 struct _Invoke1;
     54 // 成员函数,标准库当中传递
     55 // _FirstTy的作用是用来判断 _Callable的Class是否是_FirstTy的Class或者Parent Class
     56 // 这里为了简化不再判断
     57 template <typename _Callable, typename _FirstTy, typename _Decayed>
     58 struct _Invoke1<_Callable, _FirstTy, _Decayed, true, false> : _InvokeMemFunc
     59 {
     60 };
     61 // 成员变量
     62 template <typename _Callable, typename _FirstTy, typename _Decayed>
     63 struct _Invoke1<_Callable, _FirstTy, _Decayed, false, true> : _InvokeMemObj
     64 {
     65 };
     66 // 普通函数
     67 template <typename _Callable, typename _FirstTy, typename _Decayed>
     68 struct _Invoke1<_Callable, _FirstTy, _Decayed, false, false> : _InvokeFunction
     69 {
     70 };
     71 // =========================================================================
     72 // 第一步
     73 // 本层先把无参数的直接筛选出来了
     74 template <typename _Callable, typename... _Types>
     75 struct _Invoke;
     76 // 无参数,必定是一个普通函数
     77 template <typename _Callable>
     78 struct _Invoke<_Callable> : _InvokeFunction
     79 {
     80 };
     81 // 有一个或多个参数,可能是普通函数,成员函数,数据成员
     82 template <typename _Callable, typename _FirstTy, typename... _Types>
     83 struct _Invoke<_Callable, _FirstTy, _Types...> : _Invoke1<_Callable, _FirstTy>
     84 {
     85 };
     86 // 通过Invoke函数进行一层封装,使其使用更加贴合实际
     87 template <typename _Callable, typename... _Types>
     88 auto Invoke(_Callable &&obj, _Types &&...argv)
     89 {
     90     return _Invoke<_Callable, _Types...>::_Call(std::forward<_Callable>(obj), std::forward<_Types>(argv)...);
     91 }
     92 // ========================================================================
     93 // 测试代码
     94 void sum(int a, int b, int c)
     95 {
     96     std::cout << a + b + c << std::endl;
     97 }
     98 struct Foo
     99 {
    100     Foo(int num) : num_(num) {}
    101     void print_add(int i) const { std::cout << num_ + i << '
    '; }
    102     int num_;
    103 };
    104 int main()
    105 {
    106     Foo foo(123);
    107     Invoke(sum, 1, 2, 3);
    108     Invoke([=]() {});
    109     Invoke(&Foo::print_add, foo, 1);
    110     Invoke(&Foo::print_add, &foo, 1);
    111     auto n = Invoke(&Foo::num_, &foo);
    112     auto n1 = Invoke(&Foo::num_, foo);
    113     return 0;
    114 }
    View Code

     输出资料:

    参考资料

    1. C++:模板元编程=>std::invoke源码分析及其实现

  • 相关阅读:
    【转】什么是5G?居然有人用漫画把它讲得如此接地气!
    【转】Centos下编译升级安装Boost
    【转】SSH穿越跳板机:一条命令跨越跳板机直接登陆远程计算机
    部署JupyterLab和pyalgotrade搭建web策略回测环境
    [转]Linux中python3.6+ipython+Jupyter Notebook环境
    环境命令备忘
    [转]微软商店 打开就显示无法加载该页面 代码0x80131500?
    [转]Centos 7 安装部署 GitLab 服务器
    [转]本文采用all-in-one(一体化的)安装OpenShift
    [转]Linux编译和安装boost库
  • 原文地址:https://www.cnblogs.com/sunbines/p/14969015.html
Copyright © 2020-2023  润新知