• C++模板元编程


    本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的Win32库去。

    逻辑结构和递归说白了就是做了一个If,一个For_N,If就和Excel里的If一样,For_N是把一个模板结构迭代N遍,为了所谓的方便,把If做成了宏,写起来还挺有意思的

     1 template<typename TTest, typename TTrue, typename TFalse>
     2 struct If;
     3 
     4 template<typename TTrue, typename TFalse>
     5 struct If<Bool<true>, TTrue, TFalse>
     6 {
     7     using Result = TTrue;
     8 };
     9 
    10 template<typename TTrue, typename TFalse>
    11 struct If<Bool<false>, TTrue, TFalse>
    12 {
    13     using Result = TFalse;
    14 };
    15 
    16 template<typename TTimes, template<typename TResult> typename TProc, typename TDefVal>
    17 struct FOR_N;
    18 
    19 template<template<typename TResult> typename TProc, typename TDefVal, int VTimes>
    20 struct FOR_N<Int<VTimes>, TProc, TDefVal>
    21 {
    22     using Result = typename TProc<
    23         typename FOR_N<
    24             Int<VTimes - 1>,
    25             TProc,
    26             TDefVal
    27         >::Result
    28     >::Result;
    29 };
    30 
    31 template<template<typename TResult> typename TProc, typename TDefVal>
    32 struct FOR_N<Int<0>, TProc, TDefVal>
    33 {
    34     using Result = typename TDefVal;
    35 };
    36 
    37 #if defined SIMPLIFIED_TML
    38 
    39 #define IF If<
    40 #define THEN ,
    41 #define ELSE ,
    42 #define NOELSE , void
    43 #define NOTHEN , void
    44 #define ENDIF >::Result
    45 #define ELIF ELSE IF
    46 
    47 #endif

    用法就不给了,不会写单元测试

    然后是列表的又一部分零碎的东西,Filter就是按照给定的一元谓词筛选整个列表,MapNone和FilterNone属于什么也不做/直接返回true的默认操作,ListGeneration是从给定的列表中生成列表,就像haskell的列表推导式一样,说白了就是Filter一下再Map一下,组合起来挺有意思的,Range就是给定一个类型和上下界,生成一个连续的区间,这里突然想到还可以自定义步长,懒得改了就这样。

     1 template<template<typename TArg> typename TFilter, typename T>
     2 struct ListFilter;
     3 
     4 template<template<typename TArg> typename TFilter, typename... TArgs>
     5 struct ListFilter<TFilter, List<TArgs...>>
     6 {
     7     using Param = List<TArgs...>;
     8     using Result = typename ListConnect<
     9         typename If<
    10             typename TFilter<typename Param::First>::Result,
    11             List<typename Param::First>,
    12             List<>
    13         >::Result,
    14         typename ListFilter<
    15             TFilter, 
    16             typename Param::Rest
    17         >::Result
    18     >::Result;
    19 };
    20 
    21 template<template<typename TArg> typename TFilter, typename TLast>
    22 struct ListFilter<TFilter, List<TLast>>
    23 {
    24     using Param = List<TLast>;
    25     using Result = typename If<
    26         typename TFilter<typename Param::First>::Result,
    27         List<typename Param::First>,
    28         List<>
    29     >::Result;
    30 };
    31 
    32 template<typename T>
    33 struct MapNone
    34 {
    35     using Result = T;
    36 };
    37 
    38 template<typename T>
    39 struct FilterNone
    40 {
    41     using Result = Bool<true>;
    42 };
    43 
    44 template<template<typename TVal> typename TProcToVal, template<typename TVal> typename TFilterProc, typename... TSeq>
    45 struct ListGeneration;
    46 
    47 template<template<typename TVal> typename TProcToVal, template<typename TVal> typename TFilterProc, typename... TSeq>
    48 struct ListGeneration<TProcToVal, TFilterProc, List<TSeq...>>
    49 {
    50     using FilterResult = typename ListFilter<TFilterProc, List<TSeq...>>::Result;
    51     using Result = typename ListMap<TProcToVal, FilterResult>::Result;
    52 };
    53 
    54 template<typename TType, TType VBegin, TType VEnd, TType VCurr = VBegin>
    55 struct Range
    56 {
    57     using Result = typename ListConnect<
    58         List<PODType<TType, VCurr>>, 
    59         typename If<
    60             Bool<VCurr < VEnd>, 
    61             typename Range<TType, VBegin, VEnd, VCurr + 1>::Result,
    62             List<>
    63         >::Result
    64     >::Result;
    65 };

    用起来还算很爽

    1 ListGeneration<Mul2, FilterNone, Range<int, 0, 63>::Result>::Result list2;

    Mul2是一个定义好的操作,就是接受一个类型值,然后把他乘以2,C++模板的递归层数最多不能超过255原来是指整个表达式的递归层数啊,我这里上界最多写到63就不能写下去了。

    SFINAE,模板替换失败不是一个错误,在编译器根据模板寻找重载函数的时候,如果一个重载的模板替换失败,那么编译器会去寻找其他的重载,直到最后找不到了再报错,由此可以通过一组函数重载过一个过滤器,根据不同的模板参数执行做不同的返回值,通过返回值来达到类型筛选和查错的目的。

    C++17的Concept也是基于SFINAE的,好激动。

    只看了type SFINAE,expression的还没看,也不准备看了,感觉没什么卵用,还是过段时间买那本C++模板元编程系统学习一下吧。

    这里翻译了一下cppreference.com上的东西:

    以下属于SFINAE错误

    • 尝试实例化一个包含多个不同长度包的包扩展(没看懂,这是什么意思)
    • 尝试创建一个void数组,引用的数组,函数的数组,抽象类的数组,负数或零长度的数组
    • 尝试在::运算符左侧使用一个非类或枚举类型
    • 尝试使用一个类型的成员,若:尝试创建一个指向引用的指针
      • 该类型不包含此成员
      • 在需要类型的地方,这个成员不是类型
      • 在需要模板的地方,这个成员不是模板类型
      • 在需要非类型的地方,这个成员不是非类型
    • 尝试创建一个void引用
    • 尝试创建一个指向T的成员的指针,但T不是类类型
    • 尝试给非类型模板参数一个错误类型的值
    • 尝试在以下情形进行一个无效转换:尝试创建一个参数是void类型的函数
      • 在模板参数表达式中
      • 在函数声明表达式中
    • 尝试创建一个返回函数或数组的函数
    • 尝试创建一个const volatile修饰的函数
    • 尝试创建一个参数或返回值是抽象类的函数

    自己也没写什么东西,对这套路子不是很熟,等我把C++那些奇怪的语法和指针声明什么的弄明白了这里也就该差不多了。

  • 相关阅读:
    activeMq-1 快速入门
    netty2 案例:数据通信
    SQL学习分享之数据链接(二)
    SQL学习 (一)
    CSS的定位重叠
    CSS 伪类 学习
    Jmeter 初学(三)
    玩转codeacademy (三)
    玩转codecademy (二)
    玩转codecademy(首次体会对象的乐趣) (一)
  • 原文地址:https://www.cnblogs.com/pointer-smq/p/4780635.html
Copyright © 2020-2023  润新知