这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D>>>的设计要好看不少。

List有一个很巧妙的继承,只有那么做才能使用类似于List<>::Rest的写法,直接定义成template<typename T, typename... TArgs>List是不行的。

Change这里可以给一个args...换另一个包装,这里感谢lyp菊苣告诉我原来template里还能接着套template,为我自己瞎摸索TML的道路开拓了另一片新天地。

scanf和foldl的原理大致基本相同,但是以我的智商是没法在短时间内把他们统一到一起了。

PrintList似乎只能使用函数来输出了。

写着写着也发现自己的模板元编程的编码和命名风格在不断完善,果然要不停写才能体会到东西。

(话说默认字体大小怎么改啊,13px才好看嘛)

 template<typename T>
struct ListGet;
template<typename... TArgs>
struct List; template<typename T, typename... TArgs>
struct ListGet<List<T, TArgs...>>
{
using First = typename T;
using Rest = List<TArgs...>;
}; template<typename... TArgs>
struct List: ListGet<List<TArgs...>>
{
using Base = ListGet<List<TArgs...>>;
using Self = List<TArgs...>;
}; template<typename T>
struct ListIsEmpty; template<typename T, typename... TArgs>
struct ListIsEmpty<List<T, TArgs...>>
{
using Result = Bool<false>;
};
template<>
struct ListIsEmpty<List<>>
{
using Result = Bool<true>;
}; template<typename A, template<typename... Args> typename B>
struct Change; template<template<typename... Args>typename A, template<typename... Args>typename B, typename... Args>
struct Change<A<Args...>, B>
{
using Result = B<Args...>;
}; template<typename T1, typename T2>
struct ListConnect; template<typename... TArgs1, typename... TArgs2>
struct ListConnect<List<TArgs1...>, List<TArgs2...>>
{
using Result = typename List<TArgs1..., TArgs2...>;
};
template<typename T>
struct ListReverse; template<typename... TArgs>
struct ListReverse<List<TArgs...>>
{
using Param = typename List<TArgs...>;
using Result = typename ListConnect<
typename ListReverse<
typename Param::Rest
>::Result,
typename List<typename Param::First>
>::Result;
}; template<typename T>
struct ListReverse<List<T>>
{
using Result = typename List<T>;
}; template<template<typename ST> typename TApplicative, typename T1>
struct ListMap; template<template<typename ST> typename TApplicative, typename... TArgs>
struct ListMap<TApplicative, List<TArgs...>>
{
using Param = typename List<TArgs...>;
using Result = typename ListConnect<
List<
typename TApplicative<
typename Param::First
>::Result
>,
typename ListMap<
TApplicative,
typename Param::Rest
>::Result
>::Result;
}; template<template<typename ST> typename TApplicative, typename TLast>
struct ListMap<TApplicative, List<TLast>>
{
using Param = typename List<TLast>;
using Result = typename List<typename TApplicative<TLast>::Result>;
}; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename T>
struct ListFoldLeft; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename... TArgs>
struct ListFoldLeft<TVal, TBinFunc, List<TArgs...>>
{
using Param = List<TArgs...>;
using Result = typename ListFoldLeft<
typename TBinFunc<
TVal,
typename Param::First
>::Result,
TBinFunc,
typename Param::Rest
>::Result;
}; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename TLast>
struct ListFoldLeft<TVal, TBinFunc, List<TLast>>
{
using Param = List<TLast>;
using Result = typename TBinFunc<TVal, typename Param::First>::Result;
}; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename T>
struct ListScanLeft; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename... TArgs>
struct ListScanLeft<TVal, TBinFunc, List<TArgs...>>
{
using Param = List<TArgs...>;
using Value = typename TBinFunc<
TVal,
typename Param::First
>::Result;
using Result = typename ListConnect<
List<Value>,
typename ListScanLeft<
Value,
TBinFunc,
typename Param::Rest
>::Result
>::Result;
}; template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename TLast>
struct ListScanLeft<TVal, TBinFunc, List<TLast>>
{
using Param = List<TLast>;
using Value = typename TBinFunc<
TVal,
typename Param::First
>::Result;
using Result = List<Value>;
}; template<typename T, T V, typename... TRest>
void PrintList(List<PODType<T, V>, TRest...>)
{
std::cout << V << ' ';
PrintList(List<TRest...>());
} template<typename T, T V>
void PrintList(List<PODType<T, V>>)
{
std::cout << V;
}

(果然只有静态高亮的C++代码看上去就和翔一样)

使用起来是这样的

 List<Int<>, Int<>, Int<>, Int<>> list;
ListFoldLeft<Int<>, Add, decltype(list)>::Result xxx;
ListScanLeft<Int<>, Add, decltype(list)>::Result yyy;
PrintList(yyy);

foldl1,foldr,foldr1以及对应的scanr……啊啊啊啊啊啊啊啊啊

 int main()
{
cout << L"我 整 个 人 都 递 归 了 ! ! ! ! ! ! 感 觉 自 己 充 满 了 力 量 ! ! ! ! ! !“;
main();
}

C++模板元编程 - 2 模仿haskell的列表以及相关操作的更多相关文章

  1. C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE

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

  2. 现代c++与模板元编程

    最近在重温<c++程序设计新思维>这本经典著作,感慨颇多.由于成书较早,书中很多元编程的例子使用c++98实现的.而如今c++20即将带着concept,Ranges等新特性一同到来,不得 ...

  3. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  4. C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成

    这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...

  5. C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法

    C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...

  6. 读书笔记_Effective_C++_条款四十八:了解模板元编程

    作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...

  7. c++ 模板元编程的一点体会

    趁着国庆长假快速翻了一遍传说中的.大名鼎鼎的 modern c++ design,钛合金狗眼顿时不保,已深深被其中各种模板奇技淫巧伤了身...论语言方面的深度,我看过的 c++ 书里大概只有 insi ...

  8. 一道模板元编程题源码解答(replace_type)

    今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...

  9. effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

随机推荐

  1. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  2. 释放Linux系统预留的硬盘空间【转】

    http://www.cnblogs.com/ggjucheng/archive/2012/10/07/2714294.html 前言 大多数文件系统都会保留一部分空间留作紧急情况时用(比如硬盘空间满 ...

  3. C#中有关string和byte[]转换的问题

    byte[] byteArray = System.Text.Encoding.Default.GetBytes( str ); 怎么样,够简单吧? 反过来也是一样,把byte[]转成string: ...

  4. ctf之加密

    from:http://drops.wooyun.org/tips/10002 0x01 Base64 Base64:ZXZhbCgkX1BPU1RbcDRuOV96MV96aDNuOV9qMXVfU ...

  5. MVC View中获取Url参数的值

    如果url是 /home/index?id=3 直接Request就ok. Razor方法 @Html.ViewContext.RouteData.Values["id"] @Re ...

  6. 1134 铺地毯【2011年NOIP全国联赛提高组】

    http://codevs.cn/problem/1134/ 题目描述 Description 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地 ...

  7. RequireJS 文件合并压缩

    RequireJS的define 以及require 对于我们进行简化JavaScript 开发,进行模块化的处理具有很大的帮助 但是请求加载的js 文件会有一些影响,一般的处理是对于文件进行压缩,但 ...

  8. MongoDB 入门与实例

    一.准备工作 1. 下载mongoDB 下载地址:http://www.mongodb.org/downloads 选择合适你的版本 相关文档:http://www.mongodb.org/displ ...

  9. 搭建EF6.0+MVC4搭建框架——之路由配置

    为了适应项目需求,需要将前后台的控制器和视图等文件分开,便于修改和维护: 方案一:在原有的Controller下新增Admins文件夹用于放置后台控制器文件: 控制器文件目录如下图: 视图文件目录:

  10. MySQL下载、安装和修改root密码

    一.下载地址:MySQL_5.6.22_winx64_XiaZaiBa :http://rj.baidu.com/soft/detail/12585.html?ald 二.安装软件,安装到指定的路径, ...