首页 > 编程语言 >模板元编程实战--类型列表算法

模板元编程实战--类型列表算法

时间:2023-05-12 11:12:29浏览次数:37  
标签:struct typename -- 编程 TypeList template using type 模板

这篇文章主要说明了我学习的过程,作为一种记事本来记录,它讲述了如何处理一个类型列表的拼接,查找,排序,等算法。

数据结构:

template<typename... Ts>
struct TypeList {

    struct isTypeList{};
    using type = TypeList<Ts...>;
    constexpr static size_t size = sizeof...(Ts);

    // 成员元函数,在列表的尾部添加元素
    template<typename... T>
    using append = TypeList<Ts..., T...>;
    // 成员元函数,在列表的头部添加元素
    template<typename... T>
    using prepend = TypeList<T..., Ts...>;
    // 成员元函数,将该列表转换为其他模板类
    template<template<typename...> typename T>
    using to = T<Ts...>;
};

使用该数据结构来实现各种算法。

为该结构编写一个约定的接口:

template<typename T>
concept TL = requires{
    typename T::isTypeList;
    typename T::type;
};

算法1,根据条件筛选类型:

template<TL in,template<typename> typename P,TL out = TypeList<> >
struct Filter : out {};

template<template<typename> typename P,TL out,typename T,typename... Ts>
struct Filter<TypeList<T,Ts...>,P,out>:std::conditional_t<P<T>::value,Filter<TypeList<Ts...>,P,typename out::template append<T>>,
    Filter<TypeList<Ts...>,P,out> >{};

template<TL in, template<typename> typename P, TL out = TypeList<> >
using Filter_t = Filter<in, P, out>::type;

Filter函数会根据回调函数P来决定哪些类型应该被添加到继承列表,最后将列表给out结束。

算法2,根据条件选择传递类型

template<typename T>
struct Return { using type = T; };

template<TL in,typename Init,template<typename,typename> class P>
struct Fold:Return<Init>{};

template<typename Init,template<typename,typename> class P,typename T,typename... Ts>
struct Fold<TypeList<T,Ts...>,Init,P>:Fold<TypeList<Ts...>,typename P<Init,T>::type,P>{};

template<TL in, typename Init, template<typename, typename> class P>
using Fold_t = Fold<in, Init, P>::type;

Fold函数与Filter差不多,其区别就是Fold函数包含的高阶函数P比Filter更加抽象,Fold不会做分支筛选,而是完全由高阶函数P来决定,这也就加强了他的适用性。

算法3,类型列表的拼接

template<TL... In> struct Concat;

template<TL... In> using Concat_t = typename Concat<In...>::type;

template<> struct Concat<>:TypeList<>{};

template<TL In> struct Concat<In> : TypeList<In>{};

template<TL In,TL In2,TL... Rest> struct Concat<In,In2,Rest...> : Concat_t<Concat_t<In,In2>,Rest...>{};

template<TL In, TL In2> struct Concat<In, In2> :In2::template to<In::template append>{};

将两个列表拼接起来,通过特化具有两个列表的Concat来不断地处理参数包Rest,直到它只有一个参数的时候,终止并返回。

算法4,查找

template<TL In,typename T>
class Elem {
public:
    template<typename T1,typename Y1>
    using Find = std::conditional_t<T1::value, T1, std::is_same<Y1, T> >;
    using type = Fold<In, std::false_type, Find>::type;
public:
    static constexpr bool value = type::value;
};
// 查找算法的另一种实现:
template<TL In,typename T>
struct Elem2;

template<typename... Ts,typename T>
struct Elem2<TypeList<Ts...> , T> : std::bool_constant<(false||...||std::is_same_v<T,Ts>) >{};

查找算法用于检查一个列表内,是否具有指定的元素,如果有返回一个包含该属性的数据结构。通过Fold函数来判定返回的结构应该包含什么样的属性。

算法5,去重(重复)

template<TL in>
struct unqiue {
    template<TL out,typename T>
    using Append = std::conditional_t<Elem<out, T>::value, out,typename out::template append<T> >;
    using type = Fold<in, TypeList<>, Append >::type;
};

如果Append函数发现新列表的参数包中有相同的类型,那么数据将不会加入到新的列表中。

算法6,按条件分割

template<TL in,template<typename> typename P>
struct partition {
    template<typename T>
    using NotP = std::bool_constant<!P<T>::value>;
    struct type {
        using Statisfied = Filter_t<in, P>;
        using Rest = Filter_t<in, NotP>;
    };
};

template<TL in,template<typename> typename P>
using partition_t = partition<in, P>::type;

高阶函数P决定了应该将哪些数据返回给Filter的type,相反,对P取反即可得到相对的类型表。

算法7,排序列表

template<TL in,template<typename,typename> typename Cmp>
struct Sort : TypeList<>{};

template<template<typename,typename> typename Cmp,typename Pivot,typename... Ts>
struct Sort<TypeList<Pivot, Ts...>, Cmp> {
    template<typename E>
    using LT = Cmp<E, Pivot>;

    using  P = partition_t<TypeList<Ts...>, LT>;

    using S = typename Sort<typename P::Statisfied, Cmp>::type;
    using B = typename Sort<typename P::Rest, Cmp>::type;

    using type = Concat_t<typename S::template append<Pivot>, B>;
};

template<TL in,template<typename,typename> typename Cmp>
using Sort_t = Sort<in, Cmp>::type;

通过条件展开列表,然后有Concat重新拼接。

算法只是一种思路,思路不同实现也不同,例如上面的拼接,特化的两个类型拼接为一个,下面是另一种思路。

 template<typename... T, typename... Ts> struct Concat<TypeList<T...>, TypeList<Ts...> > : TypeList<T..., Ts...> {};

目的只为了学习思路,而不是死记硬背。Fold也可以实现Filter的功能,并且也可以出现更多的变种。

一些具体是使用示例:

Sort:


    template<typename T,typename Y>
    using TypeCmp = std::bool_constant<(sizeof(T) < sizeof(Y))>;

  -----------------------------------------
using list1 = TypeList<char, double, float, long long, int, int,char>; using sq = Sort_t<list1, TypeCmp>::type; // TypeList<char,char,float,int,int,double,long long>

partition:

 

    template<typename T>
    struct F {
      static constexpr bool value = (sizeof(T) > 4);
    };

  --------------------------------------
   using list1 = TypeList<char, double, float, long long, int, int,char>; using we = partition<list1, F>::type::Rest::type; // TypeList<char,float,int,int> using wb = partition<list1, F>::type::Statisfied::type; // TypeList<double,long long>

unique:

   using list1 = TypeList<char, double, float, long long, int, int,char>;
    using t = unqiue<list1>::type;    // TypeList<char,double,float,long long,int>

Elem:

using list1 = TypeList<char, double, float, long long, int, int,char>;

constexpr bool s = Elem<list1, char>::value; //true

Fold:

template<typename T,typename Y>
using TypeSize = std::integral_constant<size_t, T::value + sizeof(Y)>;
----------------------------- using list1 = TypeList<char, double, float, long long, int, int,char>; using Type = Fold<list1, std::integral_constant<size_t, 0>, TypeSize>::type;

 

template<typename out,typename T>
struct Fun {
    using type = std::conditional_t<std::is_integral_v<T>, typename out::template append<T>, out>;
};
-----------------------------------
using list1 = TypeList<char, double, float, long long, int, int,char>;
using Type2 = Fold<list1, TypeList<>, Fun>::type;

 

Concat:

using list1 = TypeList<char, double, float, long long, int, int,char>;
using Type3 = Concat<TypeList<int, char>, TypeList<double, float>, TypeList<long long, long> >::type;

 

Filter:

template<typename T>
using gf = std::bool_constant<(sizeof(T) > 4)>;
-----------------------
 using list1 = TypeList<char, double, float, long long, int, int,char>;
 using g = Filter_t<list1, gf>::type;

 

 

标签:struct,typename,--,编程,TypeList,template,using,type,模板
From: https://www.cnblogs.com/Super-biscuits/p/17393442.html

相关文章

  • vue3 父子组件传值
    父传子组件<template><div><!--通过自定义属性传递值--><Subassembly:value="doc"/></div></template><scriptsetup>import{ref}from'vue'importSubassemblyfrom'./Subassembly.vue&#......
  • 年月日的计算
    //type:年、月或者日//data:日期//加减量functionaddOrReduceDate(type,date,num){ varnowDate=null; varstrDate=""; num=parseInt(num);//防止传入字符串报错 varseperator1="-"; varseperator2=":"; if(date==""......
  • 直流有刷电机闭环控制 主控dsp28335,直流有刷电机,采用ab编码器,进行
    直流有刷电机闭环控制主控dsp28335,直流有刷电机,采用ab编码器,进行速度闭环。有转速指令规划处理,速度环pid控制,eqep位置解算、转速解算,可以通过上位机控制电机正反转,发送指令等。可以直接用上位机看波形,也可以在matlab中分析数据。通过调节pid参数,在matlab中对比转速响应曲线,直观的......
  • spring出现依赖关系形成循环问题,The dependencies of some of the beans in the appli
    出现这个问题大多使用的springboot都是在2.6.x以上,springboot在2.6.x就将依赖循环禁用了,解决方式有以下几种:解决方式:1、第一种解决方式:可以优化自己程序的逻辑,优化bean的依赖关系,只要不形成一个环状就不会出该问题了 2、第二种解决方式:可以使用@Lazy注解(懒加载)和@Autowired注......
  • ......
  • vue 存储cookie 与使用
    安装cookie依赖包npmi@vueuse/integrations安装cookienpmiuniversal-cookie使用cookieimport{useCookies}from"@vueuse/integrations/useCookies"constcookie=useCookies();存取cookiecookie.set("token","123456789")获取cookiecookie.......
  • 霍尔自学习 stm32f4平台的有hall方波控制工程, 在这这个基础上增加了
    霍尔自学习stm32f4平台的有hall方波控制工程,在这这个基础上增加了hall自学习流程,增加了上位机通信协议,使得电机相线和hall线可以任意接,都可以一键学习,运行电机。keil工程,带结果校验,带上位机。以上描述的资料。提供源码、上位机、hall自学习方法、有感方波控制的所有问题,包括一些超......
  • 高频注入和滑模观测器 dsp平台完整工程,包括smo和hfi,转子初始
    高频注入和滑模观测器dsp平台完整工程,包括smo和hfi,转子初始位置辩识等,工程编译0错误0警告,无任何lib,无任何lib,算法全开源,核心代码部分基本全注释了。ID:97300666467456425......
  • uart RS232通信
    波特率指的是异步时钟的频率。sourcecodetopmodule`timescale1ns/1ps////////////////////////////////////////////////////////////////////////////////////Company://Engineer:////CreateDate:2023/04/2815:48:05//DesignName://ModuleName:ua......
  • dsp28335串口升级方案 提供bootloader源代码,用户工程源代码,上位
    dsp28335串口升级方案提供bootloader源代码,用户工程源代码,上位机以及上位机源代码。提供使用说明,通信协议。ID:441000666865117012......