C++模板编程——typelist的实现

打印 上一主题 下一主题

主题 988|帖子 988|积分 2964

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
文章最后给出了汇总的代码,可直接运行
1. typelist是什么

typelist是一种用来操作类型的容器。和我们所熟知的vector、list、deque雷同,只不过typelist存储的不是变量,而是类型。
typelist简朴来说就是一个类型容器,可以或许提供一系列的操作。
本文将展示使用元编程实现typelist。
2. 要实现的typelist的接口

在此罗列一下即将要编写的typelist的所有接口:
   

  • typelist:要实现的容器类型。
  • front<typelist>:获取容器中的第一个元素。
  • size<typelist>:获取容器的元素数量。
  • pop_front<typelist, elem>:移出第一个元素。
  • push_front<typelist, elem>:向开头插入一个元素。
  • push_back<typelist, elem>:向末端插入一个元素。
  • replace_front<typelist, elem>:更换第一个元素。
  • is_empty<typelist>:判断是否为空。
  • find<typelist, index>:查找下标为index的元素。
  • get_maxsize_type<typelist>:容器中尺寸(sizeof)最大的元素。
  • reverse<typelist>:翻转容器中的元素。 
  • filter<typelist, Pre>:根据谓词Pre来过滤typelist中的类型。Pre应该是一个类模板,接受一个类型模板参数,并拥有一个bool类型的静态变量value,value为false时将该类型剔除typelist。
  3. 接口实现

3.1 容器

  1. template<typename... Elems>
  2. struct typelist{};
复制代码
3.2 front<typelist>

  1. template<typename TPLT>// typelist的简写
  2. struct front;
  3. struct front<typelist<FirstElem, OtherElems...>>
  4. {
  5.     using type = FirstElem;
  6. };
复制代码
3.3 size<typelist>

  1. template<typename TPLT>
  2. struct size;
  3. template<typename... Elems>
  4. struct size<typelist<Elems...>>
  5. {
  6.     static inline const value = sizeof...(Elems);
  7. };
复制代码
3.4 pop_front<typelist, elem>

  1. template<typename TPLT>
  2. struct pop_front;
  3. template<typename FirstElem, typename... OtherElems>
  4. struct pop_front<typelist<FirstElem, OtherElems...>
  5. {
  6.     using type = typelist<OtherrElems...>;
  7. };
复制代码
3.5 push_front<typelist, elem>

  1. template<typename TPLT, typename newElem>
  2. struct push_front;
  3. template<typename... Elems, typename newElem>
  4. struct push_front<typelist<Elems...>, newElem>
  5. {
  6.     using type = typelist<newElem, Elems...>;
  7. };
复制代码
3.6 push_back<typelist, elem>

  1. template<typename TPLT, typename newElem>
  2. struct push_back;
  3. template<typename... Elems, typename newElem>
  4. struct push_back<typelist<Elems...>, newElem>
  5. {
  6.     using type = typelist<Elems..., newElem>;
  7. };
复制代码
3.7 replace_front<TPLT, elem>

  1. template<typename TPLT, typename Elem>
  2. struct replace_front;
  3. template<typename FirstElem, typename... OtherElems, typename Elem>
  4. struct replace_front<typelist<FirstElem, OtherElems...>, Elem>
  5. {
  6.     using type = typelist<Elem, OtherElems...>;
  7. };
复制代码
3.8 is_empty<TPLT>

  1. template<typename TPLT>
  2. struct is_empty;
  3. template<typename... Elems>
  4. struct is_empty
  5. {
  6.     static inline const bool value = sizeof...(Elems) == 0;
  7. };
复制代码
3.9 find<typelist, index>

  1. template<typename TPLT, size_t index>
  2. struct find : find<typename pop_front<TPLT>::type, index - 1>
  3. {
  4.        
  5. };
  6. template<typename TPLT>
  7. struct find<TPLT, 0> :front<TPLT>
  8. {
  9. };
复制代码
3.10 get_maxsize_type<typelist>

  1. template<typename TPLT>
  2. struct get_maxsize_type
  3. {
  4. private:
  5.         using FirstType = typename front<TPLT>::type;
  6.         using RemainLT = typename pop_front<TPLT>::type;
  7.         using RemainMaxType = typename get_maxsize_type<RemainLT>::type;
  8. public:
  9.         using type = conditional_t < (sizeof(FirstType) > sizeof(RemainMaxType)),
  10.                 FirstType, RemainMaxType >;
  11. };
  12. template<typename Elem>
  13. struct get_maxsize_type<typelist<Elem>>
  14. {
  15.         using type = Elem;
  16. };
  17. template<>
  18. struct get_maxsize_type<typelist<>>;
复制代码
3.11 reverse<typelist>

  1. template<typename TPLT>
  2. struct reverse
  3. {
  4. private:
  5.         using FirstElem = typename front<TPLT>::type;
  6.         using RemainTL = typename pop_front<TPLT>::type;
  7.         using ReversedRemainTL = typename reverse<RemainTL>::type;
  8. public:
  9.         using type = typename push_back<ReversedRemainTL, FirstElem>::type;
  10. };
  11. template<>
  12. struct reverse<typelist<>>
  13. {
  14.         using type = typelist<>;
  15. };
复制代码

  1. template<typename TPLT, bool = is_empty<TPLT>::value>
  2. struct reverse;
  3. template<typename TPLT>
  4. struct reverse<TPLT, false>
  5. {
  6. private:
  7.         using FirstElem = typename front<TPLT>::type;
  8.         using RemainTL = typename pop_front<TPLT>::type;
  9.         using ReversedRemainTL = typename reverse<RemainTL>::type;
  10. public:
  11.         using type = typename push_back<ReversedRemainTL, FirstElem>::type;
  12. };
  13. template<typename TPLT>
  14. struct reverse<TPLT, true>
  15. {
  16.         using type = typelist<>;
  17. };
复制代码
3.12 filter<typelist, Pre>

  1. // 根据谓词过滤元素,谓词应该是一个类模板,接受一个类型参数,并且具有静态bool变量,false表示过滤掉该类型
  2. template<typename TPLT, template<typename>typename Pre>
  3. struct filter;
  4. template<typename FirstElem, typename... OtherElems, template<typename>typename Pre>
  5. struct filter<typelist<FirstElem, OtherElems...>, Pre>
  6. {
  7. private:
  8.         using RemainFilteredTL = typename filter<typelist<OtherElems...>, Pre>::type;
  9. public:
  10.         using type = std::conditional_t< Pre<FirstElem>::value,
  11.                 typename push_front<RemainFilteredTL, FirstElem>::type,
  12.                 RemainFilteredTL >;
  13. };
  14. template<template<typename>typename Pre>
  15. struct filter<typelist<>, Pre>
  16. {
  17.         using type = typelist<>;
  18. };
复制代码
  1. // 测试使用的类模板,用以剔除某个指定的类型
  2. template<typename InputType, typename FilterType = double>
  3. struct test_filter
  4. {
  5.         static constexpr bool value = !std::is_same_v<InputType, FilterType>;  //如果类型是int,就输出false,int不通过
  6. };
复制代码
 
4. 完备代码


  1. #include <iostream>
  2. #include <type_traits>
  3. #include "typegetter.hpp"
  4. using namespace std;
  5. /*
  6. */
  7. namespace myTypeList
  8. {
  9.         template<typename... Elems>
  10.         struct typelist {};
  11.         template<typename TPLT>
  12.         struct front;
  13.         template<typename FirstElem, typename... OtherElems>
  14.         struct front < typelist<FirstElem, OtherElems...>>
  15.         {
  16.                 using type = FirstElem;
  17.         };
  18.         template<typename TPLT>
  19.         struct size;
  20.         template<typename... Elems>
  21.         struct size<typelist<Elems...>>
  22.         {
  23.                 static const inline size_t value = sizeof...(Elems);
  24.         };
  25.         template<typename TPLT>
  26.         struct is_empty;
  27.         template<typename... Elems>
  28.         struct is_empty<typelist<Elems...>>
  29.         {
  30.                 static constexpr bool value = sizeof...(Elems) == 0;
  31.         };
  32.         template<typename TPLT>
  33.         struct pop_front;
  34.        
  35.         template<typename FirstElem, typename... OtherElems>
  36.         struct pop_front< typelist<FirstElem, OtherElems...> >
  37.         {
  38.                 using type = typelist<OtherElems...>;
  39.         };
  40.         template<typename TPLT, typename newElem>
  41.         struct push_front;
  42.         template<typename... Types, typename newElem>
  43.         struct push_front<typelist<Types...>, newElem>
  44.         {
  45.                 using type = typelist<newElem, Types...>;
  46.         };
  47.         template<typename TPLT, typename newElem>
  48.         struct push_back;
  49.         template<typename... Types, typename newElem>
  50.         struct push_back<typelist<Types...>, newElem>
  51.         {
  52.                 using type = typelist<Types..., newElem>;
  53.         };
  54.         template<typename TPLT, typename newElem>
  55.         struct replace_front;
  56.         template<typename FirstElem, typename... OtherElems, typename newElem>
  57.         struct replace_front<typelist<FirstElem, OtherElems...>, newElem>
  58.         {
  59.                 using type = typelist<newElem, OtherElems...>;
  60.         };
  61.        
  62.         template<typename TPLT, size_t index>
  63.         struct find : find<typename pop_front<TPLT>::type, index - 1>
  64.         {
  65.                
  66.         };
  67.         /*
  68.                 和下面的写法是等价的
  69.         template<typename TPLT, size_t index>
  70.         struct find
  71.         {
  72.                 using type = typename find<typename pop_front<TPLT>::type, index - 1>::type;
  73.         };
  74.         */
  75.         template<typename TPLT>
  76.         struct find<TPLT, 0> :front<TPLT>
  77.         {
  78.         };
  79.         /*
  80.                 get_maxsize_type: 获取typelist中尺寸最大的类型
  81.         */
  82.         template<typename TPLT>
  83.         struct get_maxsize_type
  84.         {
  85.         private:
  86.                 using FirstElem = typename front<TPLT>::type;
  87.                 using RemainLT = typename pop_front<TPLT>::type;
  88.                 using RemainMaxElem = typename get_maxsize_type<RemainLT>::type;
  89.         public:
  90.                 using type = conditional_t < (sizeof(FirstElem) > sizeof(RemainMaxElem)),
  91.                         FirstElem, RemainMaxElem >;
  92.         };
  93.         template<typename Elem>
  94.         struct get_maxsize_type<typelist<Elem>>
  95.         {
  96.                 using type = Elem;
  97.         };
  98.         template<>
  99.         struct get_maxsize_type<typelist<>>;
  100.         /*
  101.                 reverse: 翻转typelist
  102.         */
  103.         /*
  104.        
  105.         // 版本一
  106.         template<typename TPLT>
  107.         struct reverse
  108.         {
  109.         private:
  110.                 using FirstElem = typename front<TPLT>::type;
  111.                 using RemainTL = typename pop_front<TPLT>::type;
  112.                 using ReversedRemainTL = typename reverse<RemainTL>::type;
  113.         public:
  114.                 using type = typename push_back<ReversedRemainTL, FirstElem>::type;
  115.         };
  116.         template<>
  117.         struct reverse<typelist<>>
  118.         {
  119.                 using type = typelist<>;
  120.         };
  121.         */
  122.         template<typename TPLT, bool = is_empty<TPLT>::value>
  123.         struct reverse;
  124.         template<typename TPLT>
  125.         struct reverse<TPLT, false>
  126.         {
  127.         private:
  128.                 using FirstElem = typename front<TPLT>::type;
  129.                 using RemainTL = typename pop_front<TPLT>::type;
  130.                 using ReversedRemainTL = typename reverse<RemainTL>::type;
  131.         public:
  132.                 using type = typename push_back<ReversedRemainTL, FirstElem>::type;
  133.         };
  134.         template<typename TPLT>
  135.         struct reverse<TPLT, true>
  136.         {
  137.                 using type = typelist<>;
  138.         };
  139.         // 根据谓词过滤元素,谓词应该是一个类模板,接受一个类型参数,并且具有静态bool变量,false表示过滤掉该类型
  140.         template<typename TPLT, template<typename>typename Pre>
  141.         struct filter;
  142.         template<typename FirstElem, typename... OtherElems, template<typename>typename Pre>
  143.         struct filter<typelist<FirstElem, OtherElems...>, Pre>
  144.         {
  145.         private:
  146.                 using RemainFilteredTL = typename filter<typelist<OtherElems...>, Pre>::type;
  147.         public:
  148.                 using type = std::conditional_t< Pre<FirstElem>::value,
  149.                         typename push_front<RemainFilteredTL, FirstElem>::type,
  150.                         RemainFilteredTL >;
  151.         };
  152.         template<template<typename>typename Pre>
  153.         struct filter<typelist<>, Pre>
  154.         {
  155.                 using type = typelist<>;
  156.         };
  157. }
  158. class A {};
  159. // 测试使用的类模板,用以剔除某个指定的类型
  160. template<typename InputType, typename FilterType = double>
  161. struct test_filter
  162. {
  163.         static constexpr bool value = !is_same_v<InputType, FilterType>;  //如果类型是int,就输出false,int不通过
  164. };
  165. int main()
  166. {
  167.         using TPL_1 = myTypeList::typelist<char, short, char, int, double, int, long, A, double>;
  168.         using TPL_2 = myTypeList::typelist<>;
  169.         cout << "----------------------------------" << endl;
  170.         cout << "TPLT_1 为:" << TypeGetter<TPL_1>::name << endl;
  171.         cout << "TPLT_2 为:" << TypeGetter<TPL_2>::name << endl;
  172.         cout << "----------------------------------" << endl;
  173.         cout << "TPL_1 的第一个类型为" << TypeGetter< myTypeList::front<TPL_1>::type >::name << endl;
  174.         //cout << "TPL_2 的第一个类型为" << TypeGetter< myTypeList::front<TPL_2>::type >::name << endl;
  175.         cout << "TPL_1 的size为:" << myTypeList::size<TPL_1>::value << endl;
  176.         cout << "TPL_2 的size为:" << myTypeList::size<TPL_2>::value << endl;
  177.         cout << "TPL_1 的pop_front为:" << TypeGetter< myTypeList::pop_front< TPL_1 >::type >::name << endl;
  178.         //cout << "TPL_2 的pop_front为:" << TypeGetter< myTypeList::pop_front< TPL_2 >::type >::name << endl;
  179.         cout << "TPL_1 push_front bool 为:" << TypeGetter< myTypeList::push_front<TPL_1, bool>::type>::name << endl;
  180.         cout << "TPL_2 push_front bool 为:" << TypeGetter< myTypeList::push_front<TPL_2, bool>::type>::name << endl;
  181.         cout << "TPL_1 push_back bool 为:" << TypeGetter< myTypeList::push_back<TPL_1, bool>::type>::name << endl;
  182.         cout << "TPL_2 push_back bool 为:" << TypeGetter< myTypeList::push_back<TPL_2, bool>::type>::name << endl;
  183.         cout << "TPL_1 replace_front with char 为:" << TypeGetter < myTypeList::replace_front< TPL_1, char >::type>::name << endl;
  184.         cout << "TPL_1 index 2 type 为:" << TypeGetter< myTypeList::find<TPL_1, 2>::type > ::name << endl;
  185.         cout << "TPL_1 max size type 为:" << TypeGetter<myTypeList::get_maxsize_type<TPL_1>::type>::name << endl;
  186.         cout << "TPL_1         为:" << TypeGetter<TPL_1>::name << endl;
  187.         cout << "TPL_1 reverse 为:" << TypeGetter<myTypeList::reverse<TPL_1>::type>::name << endl;
  188.         cout << "TPL_1 经过int_filter过滤为:" << TypeGetter<myTypeList::filter<TPL_1, test_filter>::type>::name << endl;
  189.         cout << "TPL_2 经过int_filter过滤为:" << TypeGetter<myTypeList::filter<TPL_2, test_filter>::type>::name << endl;
  190.         return 0;
  191. }
复制代码
typegetter.hpp的代码如下所示:
  1. #pragma once
  2. #include <string>
  3. #include "boost/type_index.hpp"
  4. template<typename T>
  5. class TypeGetter
  6. {
  7. public:
  8.         static inline const std::string name = boost::typeindex::type_id_with_cvr<T>().pretty_name();
  9. };
复制代码

 运行结果如下: 



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表