1. TupleHelper的主要功能

(1)打印:由于tuple中的元素是可变参数模板,外部并不知道内部到底是什么数据,有时调试时需要知道其具体值,希望能打印出tuple中所有的元素值。

(2)根据元素值获取索引位置:tuple接口中有根据索引位置获取元素的接口,根据元素值来获取索引位置是相反的做法。

(3)获取索引:在运行期根据索引获取索引位置的元素。

(4)遍历tuple:类似于std::for_each算法,可以将函数对象应用于tuple的每个元素

(5)反转tuple:将tuple中的元素逆序。

(6)应用于函数:将tuple中的元素进行一定的转换,使之成为函数的入参

2. 打印tuple

(1)通过模板特化和递归来展开打印tuple

  ①tuple内部的元素个数和类型是不固定的,需要需要用std::get<N>(tuple)来获取元素。

  ②模板特化和递归调用展开tuple的本质就是通过整型模板参数递减来实现的。TuplePrint<decltype(tup), N>::print(tup);通用N来控制递归调用,直到N递减为1.

  ③PrintTuple2(tup)是辅助函数,可以减少外面调用的入参,方面调用TuplePrinter。

(2)通过索引序列来展开并打印tuple

  ①根据tuple的参数Args…,创建一个可变的索引序列:make_index<Args…>::type

  ②根据索引序列来获取tuple中对应位置的元素,并转化为另一种可供print_impl函数使用的参数包:std::get<Indexes>(tup)…

  ③本质上是将tuple通过可变索引序列,转化为一个可变参数模板参数包

【编程实验】tuple的打印

//TpIndex.hpp

  1. #ifndef _TP_INDEXES_H_
  2. #define _TP_INDEXES_H_
  3.  
  4. namespace TupleHelper
  5. {
  6.  
  7. //******tuple参数的索引序列****************/
  8.  
  9. //*************递增整数序列*******************
  10. //第1种方法
  11. template<int...>
  12. struct IndexTuple{};
  13.  
  14. //前向声明
  15. template<int I, typename IndexTuple, typename... Types>
  16. struct make_indexes_impl;
  17.  
  18. //定义递归函数(产生递增的整数序列)
  19. //各参数:I用于控制递归次数,Indexes:当前己产生的整数序列,T和Types...:将Types包分解T和Types...两部分
  20. template<int I, int... Indexes, typename T, typename... Types>
  21. struct make_indexes_impl<I, IndexTuple<Indexes...>, T, Types...>
  22. {
  23. //由于Types参数包被分解和T和Types...两部分,所以Types...的参数个数会逐渐减少
  24. //同时IndexTuple<Indexs...,I>会在当前Indexes整数序列的后面加上一个递增的I,即IndexTuple<Indexes..., I>
  25. //因此,是一个递增的整数序列
  26. using type = typename make_indexes_impl<I+, IndexTuple<Indexes..., I>, Types...>::type;
  27. };
  28.  
  29. //递归终止
  30. template<int I, int... Indexes>
  31. struct make_indexes_impl<I, IndexTuple<Indexes...>>
  32. {
  33. using type = IndexTuple<Indexes...>;
  34. };
  35.  
  36. //类型萃取
  37. //调用方法如:make_indexes<double, char, int>
  38. template<typename... Types>
  39. struct make_indexes : make_indexes_impl<, IndexTuple<>, Types...>
  40. {};
  41.  
  42. //第2种方法:
  43. template<int N, int... Indexes>
  44. struct make_indexes2 : make_indexes2<N-, N-, Indexes...>{};
  45.  
  46. //termination condition
  47. template<int... Indexes>
  48. struct make_indexes2<, Indexes...>
  49. {
  50. using type = IndexTuple<Indexes...>;
  51. };
  52.  
  53. //第3种方法
  54. template<int end, int cur, int... Indexes>
  55. struct make_indexes3 : make_indexes3<end, cur + , Indexes..., cur>{};
  56.  
  57. //cur == end, the list has been built
  58. template<int end, int... Indexes>
  59. struct make_indexes3<end, end, Indexes...>
  60. {
  61. using type = IndexTuple<Indexes...>;
  62. };
  63.  
  64. //*************递减整数序列*******************
  65. //前向声明
  66. template<int I, typename IndexTuple, typename... Types>
  67. struct make_indexes_reverse_impl;
  68.  
  69. //产生递减整数序列
  70. template<int I, int... Indexes, typename T, typename... Types>
  71. struct make_indexes_reverse_impl<I, IndexTuple<Indexes...>, T, Types...>
  72. {
  73. using type = typename make_indexes_reverse_impl<I-, IndexTuple<Indexes..., I->, Types...>::type;
  74. };
  75.  
  76. //递归终止
  77. template<int I, int... Indexes>
  78. struct make_indexes_reverse_impl<I, IndexTuple<Indexes...>>
  79. {
  80. using type = IndexTuple<Indexes...>;
  81. };
  82.  
  83. //类型萃取
  84. //调用方法如:make_indexes<double, char, int>
  85. template<typename... Types>
  86. struct make_reverse_indexes : make_indexes_reverse_impl<sizeof...(Types), IndexTuple<>, Types...>
  87. {};
  88.  
  89. }
  90.  
  91. #endif

//TpPrint.hpp

  1. #ifndef _TP_PRINT_H_
  2. #define _TP_PRINT_H_
  3.  
  4. #include <tuple>
  5. #include <iostream>
  6. #include "TpIndexes.hpp"
  7.  
  8. namespace TupleHelper
  9. {
  10. //*************tuple的打印*******************
  11.  
  12. //第1种方法:根据索引序列打印
  13. template<typename Last>
  14. void print_impl(Last&& last)
  15. {
  16. std::cout << " " << last << std::endl;
  17. }
  18.  
  19. template<typename Head, typename... Tail>
  20. void print_impl(Head&& head, Tail&&... tail)
  21. {
  22. std::cout << " " << head;
  23. print_impl(tail...);
  24. }
  25.  
  26. //万能转换,将tuple转成Args...
  27. template<typename... Args, int... Indexes>
  28. void tuple_print_impl(IndexTuple<Indexes...>, std::tuple<Args...>&& tup)
  29. {
  30. //取出tuple中的每个元素,并转成供print_imple使用的另一种参数包
  31. print_impl(std::forward<Args>(std::get<Indexes>(tup))...);
  32. }
  33.  
  34. //辅助函数
  35. template<typename... Args>
  36. void PrintTuple(const std::tuple<Args...>& tup) //左值版本
  37. {
  38. tuple_print_impl(typename make_indexes<Args...>::type(),
  39. std::tuple<Args...>(tup));
  40. }
  41.  
  42. template<typename... Args>
  43. void PrintTuple(std::tuple<Args...>&& tup) //右值版本
  44. {
  45. tuple_print_impl(typename make_indexes<Args...>::type(),
  46. std::forward<std::tuple<Args...>>(tup));
  47. }
  48.  
  49. //第2种方法:通过模板特化和递归来展开并打印tuple
  50. template<class Tuple, std::size_t N>
  51. struct TuplePrinter
  52. {
  53. static void print(const Tuple& t)
  54. {
  55. TuplePrinter<Tuple, N->::print(t); //深度递归
  56. std::cout << ", " << std::get<N->(t);
  57. }
  58. };
  59.  
  60. template<class Tuple>
  61. struct TuplePrinter<Tuple, >
  62. {
  63. static void print(const Tuple& t)
  64. {
  65. std::cout << ", " << std::get<>(t);
  66. }
  67. };
  68. //辅助函数
  69. template<typename... Args>
  70. void PrintTuple2(const std::tuple<Args...>& tup)
  71. {
  72. std::cout << "(";
  73. TuplePrinter<decltype(tup), sizeof...(Args)>::print(tup);
  74. std::cout <<")" << std::endl;
  75. }
  76.  
  77. //第3种方法:
  78. template<typename T, int... Indexes>
  79. void print_impl3(const T& tup, IndexTuple<Indexes...>)
  80. {
  81. //利用初始化列表
  82. int a[] = {(std::cout << std::get<Indexes>(tup) << " ",)...};
  83. (void)a;
  84. std::cout << std::endl;
  85. }
  86.  
  87. template<typename... Args>
  88. void PrintTuple3(const std::tuple<Args...>& tup)
  89. {
  90. typedef typename make_indexes<Args...>::type index_type;
  91. print_impl3(tup, index_type());
  92. }
  93.  
  94. }
  95.  
  96. #endif

//TestPrint.cpp

  1. #include <iostream>
  2. #include <tuple>
  3. #include "TpPrint.hpp"
  4.  
  5. using namespace std;
  6. using namespace TupleHelper;
  7.  
  8. int main()
  9. {
  10. //1. tuple的打印
  11. using Tuple = std::tuple<int,short, double, char, string>;
  12. Tuple tp = std::make_tuple(, , 0.5f, 'a', "ok");
  13. PrintTuple(tp);
  14. PrintTuple2(tp);
  15. PrintTuple3(tp);
  16.  
  17. return ;
  18. }
  19. /*输出结果
  20. e:\Study\C++11\27>g++ -std=c++11 test_tuple_helper.cpp
  21. e:\Study\C++11\27>a.exe
  22. 1 2 0.5 a ok
  23. (, 1, 2, 0.5, a, ok)
  24. 1 2 0.5 a ok
  25. */

3. 根据元素值获取索引位置

(1)遍历tuple并判断当前元素值是否与给定的值相等,如果相等,则返回当前索引。否则直到遍历终止时仍没找到,则返回-1。

(2)equal_val<N>(tuple, val)用于判断std::get<N>(tuple)是否等于val。

(3)查找是从tuple的最后一个元素开始的,并返回第1个匹配元素的索引位置。

(4)find_index用于递归查找。findIndex是个辅助函数,便于简化调用。

4. 在运行期根据索引位置获取元素

(1)std::get<N>(tuple):用于获取tuple中的第N个元素,但是N只能是个编译期的常量,不能是个变量(如int i)

(2)可以采用映射的方法,将运行期变量“映射”为编译期常量。(见getArgByIndex函数)。通过自增编译期常量k,将k与运行期变量index比较,当两者相等时表示映射成功,这时调用std::get<k>(tuple)来获取第k个元素值。

5. 遍历tuple

(1)先将tuple展开为可变参数模板,然后用展开可变参数模板的方法遍历tuple类

(2)遍历函数:tuple_for_each(func, tup);由于tuple中的元素类型是变化的因此func不能用lambda表达式,需要用一个泛型函数来处理tuple中的元素(见Functor仿函数)。

6. 反转tuple

(1)生成一个逆序的索引序列,目的是为了从最后一个tuple元素开始,将前面的元素一个一个取出来组成一个新的tuple。

(2)tuple_reverse可接受左右值类型的tuple参数对象。

7. 应用于函数

(1)tuple应用于函数的目的:是将tuple展开作为某个函数的入参(可能有多个参数)。

(2)实现思路:先将tuple展开转换为可变参数模板,然后这个可变参数模板应用于某个函数。

(3)本例未实现当函数返回void的情况,这可重载apply_helper函数。

8. 合并tuple

(1)将两个tuple合起来,前一个tuple中的每一个元素为key后一个tuple中的每个元素为value,组成一个pair集合。

(2)利用索引序列,将两个tuple分别展开,再将这些元素组合成一个pair集合。

【编程实验】tupleHelper的综合应用

//TpApply.hpp

  1. #ifndef _TP_APPLY_H_
  2. #define _TP_APPLY_H_
  3.  
  4. #include <tuple>
  5. #include "TpIndexes.hpp"
  6.  
  7. namespace TupleHelper
  8. {
  9.  
  10. //1. 根据元素值获取索引位置
  11. //对于可转换的类型,则直接比较
  12. template<size_t N, typename Tuple, typename T>
  13. static typename std::enable_if<std::is_convertible<typename std::tuple_element<N, Tuple>::type, T>::value ||
  14. std::is_convertible<T, typename std::tuple_element<N, Tuple>::type>::value, bool>::type
  15. equal_val(const Tuple& tp, const T& val)
  16. {
  17. return std::get<N>(tp) == val;
  18. }
  19.  
  20. //不能互转的类型,则直接返回false
  21. template<size_t N, typename Tuple, typename T>
  22. static typename std::enable_if<!(std::is_convertible<typename std::tuple_element<N, Tuple>::type, T>::value ||
  23. std::is_convertible<T, typename std::tuple_element<N, Tuple>::type>::value), bool>::type
  24. equal_val(const Tuple& tp, const T& val)
  25. {
  26. return false;
  27. }
  28.  
  29. //根据值查找索引
  30. template<int I, typename T, typename... Args> //I用于控制递归调用的次数,I-1为元素索引位置
  31. struct find_index
  32. {
  33. static int comp(const std::tuple<Args...>& tup, T&& val)
  34. {
  35. using U = typename std::remove_reference<typename std::remove_cv<T>::type>::type;
  36. using V = typename std::tuple_element<I - , std::tuple<Args...>>::type;
  37. bool bflag = std::is_convertible<U, V>::value || std::is_convertible<V, U>::value;
  38. return (bflag && equal_val<I - >(tup, val)) ?
  39. I - : //从tuple最后一个元素开始查找,当前I-1为元素的索引
  40. find_index<I - , T, Args...>::comp(tup, std::forward<T>(val));
  41. }
  42. };
  43.  
  44. template<typename T, typename... Args>
  45. struct find_index<, T, Args...>
  46. {
  47. static int comp(const std::tuple<Args...>& tup, T&& val)
  48. {
  49. using U = typename std::remove_reference<typename std::remove_cv<T>::type>::type;
  50. using V = typename std::tuple_element<, std::tuple<Args...>>::type;
  51. bool bflag = std::is_convertible<U, V>::value || std::is_convertible<V, U>::value;
  52. //递归终止,如果找到则返回0,否则返回-1
  53. return (bflag && equal_val<>(tup, val)) ? : -;
  54. }
  55. };
  56.  
  57. //辅助函数,简化调用
  58. template<typename T, typename... Args>
  59. int findIndex(const std::tuple<Args...>& tup, T&& val)
  60. {
  61. return find_index<sizeof...(Args), T, Args...>::comp(tup, std::forward<T>(val));
  62. }
  63.  
  64. //2. 在运行期根据索引位置获取元素
  65. //第1种方法:将编译期常量和运行期变量进行映射
  66. template<size_t k, typename Tuple>
  67. typename std::enable_if<(k==std::tuple_size<Tuple>::value)>::type //void
  68. getArgByIndex(size_t index, const Tuple& tp)
  69. {
  70. throw std::invalid_argument("arg index out of range");
  71. }
  72.  
  73. template<size_t k = , typename Tuple>
  74. typename std::enable_if<(k<std::tuple_size<Tuple>::value)>::type
  75. getArgByIndex(size_t index, const Tuple& tp)
  76. {
  77. if(k == index){
  78. std::cout << std::get<k>(tp)<< " ";
  79. }else{
  80. getArgByIndex<k + >(index, tp);//通过自增k,使得当k==index时输出
  81. }
  82. }
  83.  
  84. //第2种方法:通过逐步展开参数包
  85. void getArgByIndex2(size_t index, std::tuple<>& tp){}
  86.  
  87. template<typename Arg, typename... Args>
  88. void getArgByIndex2(size_t index, std::tuple<Arg, Args...>& tp)
  89. {
  90. if(index < || index >=std::tuple_size<std::tuple<Arg, Args...>>::value)
  91. throw std::invalid_argument("index is not valid");
  92.  
  93. if(index > )
  94. getArgByIndex2(index-, (std::tuple<Args...>&)tp); //tp的父类为std::tuple<Args...>
  95. //注意:父子类对象内存模型
  96. else
  97. std::cout << std::get<>(tp) << " ";
  98. }
  99.  
  100. template<typename Arg> //特化:当tuple只有一个参数时
  101. void getArgByIndex2(size_t index, std::tuple<Arg>& tp)
  102. {
  103. std::cout << std::get<>(tp) << " ";
  104. }
  105.  
  106. //3. 遍历tuple
  107. template<typename Func, typename Last>
  108. void for_each_impl(Func&& f, Last&& last)
  109. {
  110. f(std::forward<Last>(last));
  111. }
  112.  
  113. template<typename Func, typename First, typename... Rest>
  114. void for_each_impl(Func&& f, First&& first, Rest&&... rest)
  115. {
  116. f(std::forward<First>(first));
  117. for_each_impl(std::forward<Func>(f), std::forward<Rest>(rest)...); //rest为tuple中的各个元素组成的参数包
  118. }
  119.  
  120. template<typename Func, int... Indexes, typename... Args>
  121. void for_each_helper(Func&& f, IndexTuple<Indexes...>, std::tuple<Args...>&& tup)
  122. {
  123. for_each_impl(std::forward<Func>(f),
  124. std::forward<Args>(std::get<Indexes>(tup))...); //将tuple展开为可变参数模板的参数包!
  125. }
  126.  
  127. template<typename Func, int... Indexes, typename... Args>
  128. void for_each_helper(Func&& f, IndexTuple<Indexes...>, std::tuple<Args...>& tup)
  129. {
  130. for_each_impl(std::forward<Func>(f),
  131. std::forward<Args>(std::get<Indexes>(tup))...); //将tuple展开为可变参数模板的参数包!
  132. }
  133.  
  134. //tuple_for_each
  135. template<typename Func, typename... Args>
  136. void tuple_for_each(Func&& f, std::tuple<Args...>& tup)
  137. {
  138. for_each_helper(std::forward<Func>(f),
  139. typename make_indexes<Args...>::type(),
  140. tup);
  141. }
  142.  
  143. template<typename Func, typename... Args>
  144. void tuple_for_each(Func&& f, std::tuple<Args...>&& tup)
  145. {
  146. for_each_helper(std::forward<Func>(f),
  147. typename make_indexes<Args...>::type(),
  148. std::forward<std::tuple<Args...>>(tup));
  149. }
  150.  
  151. //4. 反转tuple
  152. template<class... Args, int... Indexes>
  153. auto reverse_impl(std::tuple<Args...>& tup, IndexTuple<Indexes...>&&) ->
  154. decltype(std::make_tuple(std::get<Indexes>(std::forward<std::tuple<Args...>>(tup))...))
  155. {
  156. return std::make_tuple(std::get<Indexes>(tup)...);
  157. }
  158.  
  159. template<class... Args, int... Indexes>
  160. auto reverse_impl(std::tuple<Args...>&& tup, IndexTuple<Indexes...>&&) ->
  161. decltype(std::make_tuple(std::get<Indexes>(std::forward<std::tuple<Args...>>(tup))...))
  162. {
  163. return std::make_tuple(std::get<Indexes>(std::forward<std::tuple<Args...>>(tup))...);
  164. }
  165.  
  166. template<class... Args>
  167. auto tuple_reverse(std::tuple<Args...>&& tup)->
  168. decltype(reverse_impl(std::forward<std::tuple<Args...>>(tup),typename make_reverse_indexes<Args...>::type()))
  169. {
  170. return reverse_impl(std::forward<std::tuple<Args...>>(tup),typename make_reverse_indexes<Args...>::type());
  171. }
  172.  
  173. template<class... Args>
  174. auto tuple_reverse(std::tuple<Args...>& tup)->
  175. decltype(reverse_impl(std::forward<std::tuple<Args...>>(tup),typename make_reverse_indexes<Args...>::type()))
  176. {
  177. return reverse_impl(tup, typename make_reverse_indexes<Args...>::type());
  178. }
  179.  
  180. //5. tuple应用于函数(将tuple中的元素展开成一个个参数,并传给f函数)。
  181. template<typename F, typename Tuple, int... Indexes>
  182. auto apply_helper(F&& f, IndexTuple<Indexes...>&& in, Tuple&& tup)->
  183. decltype(std::forward<F>(f)(std::get<Indexes>(tup)...))
  184. {
  185. return std::forward<F>(f)(std::get<Indexes>(tup)...);
  186. }
  187.  
  188. template<class F, class... Args>
  189. typename std::result_of<F(Args...)>::type
  190. apply(F&& f, const std::tuple<Args...>& tup)
  191. {
  192. return apply_helper(std::forward<F>(f), typename make_indexes<Args...>::type(), tup);
  193. }
  194.  
  195. //6. 合并tuple
  196. template<std::size_t N, typename T1, typename T2>
  197. using pair_type = std::pair<typename std::tuple_element<N, T1>::type, typename std::tuple_element<N, T2>::type>;
  198.  
  199. template<std::size_t N, typename T1, typename T2>
  200. pair_type<N, T1, T2> pairs(const T1& tup1, const T2& tup2)
  201. {
  202. return std::make_pair(std::get<N>(tup1), std::get<N>(tup2)); //tup1为key, tup2为value
  203. }
  204.  
  205. template<int... Indexes, typename T1, typename T2>
  206. auto pairs_helper(IndexTuple<Indexes...>, const T1& tup1, const T2& tup2)->
  207. decltype(std::make_tuple(pairs<Indexes>(tup1, tup2)...))
  208. {
  209. return std::make_tuple(pairs<Indexes>(tup1, tup2)...);
  210. }
  211.  
  212. template<typename Tuple1, typename Tuple2>
  213. auto Zip(Tuple1 tup1, Tuple2 tup2)->
  214. decltype(pairs_helper(typename make_indexes2<std::tuple_size<Tuple1>::value>::type(), tup1, tup2))
  215. {
  216. static_assert(std::tuple_size<Tuple1>::value == std::tuple_size<Tuple2>::value, "tuples should be the same size.");
  217. return pairs_helper(typename make_indexes2<std::tuple_size<Tuple1>::value>::type(), tup1, tup2);
  218. }
  219.  
  220. }
  221. #endif

//test_tuple_helper.cpp

  1. #include <iostream>
  2. #include <tuple>
  3. #include "TpPrint.hpp"
  4. #include "TpApply.hpp"
  5.  
  6. using namespace std;
  7. using namespace TupleHelper;
  8.  
  9. struct Functor
  10. {
  11. template<typename T>
  12. void operator()(T&& t) const
  13. {
  14. cout << t << " ";
  15. }
  16. };
  17.  
  18. struct PairFunctor
  19. {
  20. template<typename T>
  21. void operator()(T&& t) const
  22. {
  23. cout << "key = " << t.first << " , value = " << t.second << endl;
  24. }
  25. };
  26.  
  27. int main()
  28. {
  29. using Tuple = std::tuple<int,short, double, char, string>;
  30. Tuple tp = std::make_tuple(, , 0.5f, 'a', "ok");
  31.  
  32. //1. 根据元素值获取索引位置
  33. cout << "findIndex(tp, \"ok\")..."<< endl;
  34. int index = findIndex(tp, "ok");
  35. cout << index << endl;
  36.  
  37. //2. 在运行期根据索引位置获取元素
  38. cout << "getArgByIndex(i, tp)..."<< endl;
  39. int len = std::tuple_size<Tuple>::value;
  40. for(int i=; i<len; i++)
  41. {
  42. getArgByIndex(i, tp); //getArgByIndex<0>(i, tp);
  43. }
  44. cout << endl;
  45.  
  46. cout << "getArgByIndex2(i, tp)..."<< endl;
  47. //getArgByIndex(5, tp); //error, 索引超出范围,将抛出异常
  48. for(int i=; i<len; i++)
  49. {
  50. getArgByIndex2(i, tp); //getArgByIndex<0>(i, tp);
  51. }
  52. cout << endl ;
  53.  
  54. cout << "Traverse tuple..."<< endl;
  55. //3. 遍历tuple
  56. tuple_for_each(Functor(), std::make_tuple(,,,'b',2.0));
  57. cout << endl;
  58.  
  59. cout << "tuple_reverse(tp)..."<< endl;
  60. //4. 反转tuple
  61. auto tp2 = tuple_reverse(tp);
  62. PrintTuple(tp2);
  63. PrintTuple(tp);
  64.  
  65. //5. 将tuple应用于函数
  66. cout << "apply..."<< endl;
  67. apply([](int a, int b){cout << a + b << endl; return a + b;}, std::make_tuple(, ));
  68.  
  69. //6. 合并tuple
  70. cout << "merge..."<< endl;
  71. auto tp3 = std::make_tuple<int, short, double, char>(, , 2.5, 'a');
  72. auto tp4 = std::make_tuple<double, short, double, char>(1.5, , 2.5, 'z');
  73. auto mypairs = Zip(tp3, tp4);
  74. tuple_for_each(PairFunctor(), mypairs);
  75.  
  76. return ;
  77. }
  78. /*输出结果
  79. e:\Study\C++11\27>g++ -std=c++11 test_tuple_helper.cpp
  80. e:\Study\C++11\27>a.exe
  81. findIndex(tp, "ok")...
  82. 4
  83. getArgByIndex(i, tp)...
  84. 1 2 0.5 a ok
  85. getArgByIndex2(i, tp)...
  86. 1 2 0.5 a ok
  87. Traverse tuple...
  88. 1 3 4 b 2
  89. tuple_reverse(tp)...
  90. ok a 0.5 2 1
  91. 1 2 0.5 a ok
  92. apply...
  93. 3
  94. merge...
  95. key = 1 , value = 1.5
  96. key = 2 , value = 2
  97. key = 2.5 , value = 2.5
  98. key = a , value = z
  99. */

第27课 可变参数模板(8)_TupleHelper的更多相关文章

  1. 第26课 可变参数模板(7)_any和variant类的实现

    1. any类的实现 (1)any类: ①是一个特殊的,只能容纳一个元素的容器,它可以擦除类型,可以将何任类型的值赋值给它. ②使用时,需要根据实际类型将any对象转换为实际的对象. (2)实现any ...

  2. 第25课 可变参数模板(6)_function_traits和ScopeGuard的实现

    1. function_traits (1)function_traits的作用:获取函数的实际类型.返回值类型.参数个数和具体类型等.它能获取所有函数语义类型信息.可以获取普通函数.函数指针.std ...

  3. 第24课 可变参数模板(5)_DllHelper和lambda链式调用

    1. dll帮助类 (1)dll的动态链接 ①传统的调用方式:先调用LoadLibrary来加载dll,再定义函数指针类型,接着调用GetProcAddress获取函数地址.然后通过函数指针调用函数, ...

  4. 第23课 可变参数模板(4)_Optional和Lazy类的实现

    1. optional类的实现 (1)optional的功能 ①optional<T>的内部存储空间可能存储了T类型的值,也可能没有.只有当optional被T初始化之后,这个option ...

  5. C++反射机制:可变参数模板实现C++反射

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在Github ...

  6. C++ 0x 使用可变参数模板类 实现 C# 的委托机制

    #ifndef _ZTC_DELEGATE_H_ #define _ZTC_DELEGATE_H_ #include <vector> #include <functional> ...

  7. c++11 可变参数模板类

    c++11 可变参数模板类 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...

  8. c++11 可变参数模板函数

    c++11 可变参数模板函数 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #in ...

  9. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

随机推荐

  1. Java实现类似eval()函数或exec()函数的功能

    一篇参考博客:http://www.cnblogs.com/fangwenyu/archive/2011/10/12/2209051.html 在Python中有一个exec()函数,同样在JavaS ...

  2. shell读取mysql数据库

    select_sql="select value from glpi_configs where name='version' " db_data=`mysql -h $host ...

  3. Beta 冲刺 (3/7)

    Beta 冲刺 (3/7) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务 文字/口头描述 参与开发关键词提醒部分 展示GitHu ...

  4. top 常用

    top -c 查看进程 同时 shift +m 内存倒序

  5. C#手动改变自制窗体的大小

    Form1.cs using System;using System.Collections.Generic;using System.ComponentModel;using System.Data ...

  6. Beanshell断言

    Beanshell断言示例一:通过从数据库查询结果集,和从接口返回中解析json格式的返回内容,比较两者来验证sample请求是否成功 1>先通过JDBC PreProcessor把测试计划中所 ...

  7. Window系统下搭建GIT本地服务器

    转载:https://blog.csdn.net/qwer971211/article/details/71156055

  8. Oracle使用备忘

    初学Oracle,很多语句记不住,写在这里备忘. 1.查看某表空间的数据文件 select file_name 文件名, tablespace_name 表空间名, bytes 已使用大小M, max ...

  9. 运行gunicorn失败:[ERROR] Connection in use: ('0.0.0.0', 8000)

    参考:https://pdf-lib.org/Home/Details/5262 执行命令:gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app,遇到如下错误: [2019-0 ...

  10. JavaStudy——Java之自动拆箱与自动装箱

    java基本类型介绍 java中,基本数据类型一共有8种,详细信息如下表: 类型 大小 范围 默认值 byte 8 -128 - 127 0 short 16 -32768 - 32768 0 int ...