【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源码分析及其实现

原文地址:https://www.cnblogs.com/sunbines/p/14969015.html