C++模板元编程 - 2 模仿haskell的列表以及相关操作
这是昨天和今天写的东西,利用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的列表以及相关操作的更多相关文章
- C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE
本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的 ...
- 现代c++与模板元编程
最近在重温<c++程序设计新思维>这本经典著作,感慨颇多.由于成书较早,书中很多元编程的例子使用c++98实现的.而如今c++20即将带着concept,Ranges等新特性一同到来,不得 ...
- C++模板元编程(C++ template metaprogramming)
实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...
- C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成
这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...
- C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法
C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- c++ 模板元编程的一点体会
趁着国庆长假快速翻了一遍传说中的.大名鼎鼎的 modern c++ design,钛合金狗眼顿时不保,已深深被其中各种模板奇技淫巧伤了身...论语言方面的深度,我看过的 c++ 书里大概只有 insi ...
- 一道模板元编程题源码解答(replace_type)
今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...
- effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
随机推荐
- hdu1285 拓扑序
题意:有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩, ...
- Linux系统编程@多线程编程(二)
线程的操作 线程标识 线程的ID表示数据类型:pthread_t (内核中的实现是unsigned long/unsigned int/指向pthread结构的指针(不可移植)几种类型) 1.对两个线 ...
- 对CSS居中的一点总结
在学习前端的过程中,发现元素和文本的水平居中和垂直居中,是经常会出现的问题,在实际工作中也会经常碰到.居中的技巧有很多,但在编写代码的过程中,发现有时候技巧管用,有时候不管用,于是就将每个知道的方案都 ...
- Andorid面试问题整理
Acitivty的四中启动模式与特点. standard:默认的启动模式 singleTop:适合那种接受通知启动的页面,比如新闻客户端之类的,可能会给你推送好几次 ,但是每次都是打开同一张页面调用o ...
- Page cache和Buffer cache[转1]
http://www.cnblogs.com/mydomain/archive/2013/02/24/2924707.html Page cache实际上是针对文件系统的,是文件的缓存,在文件层面上的 ...
- SQL server 中的dbo、guest
dbo database owner 数据库的创建者,创建该对象的用户. guest 顾客 能够访问数据库中对象的数据, 要求dbo分配权限给guest, 一般给他查看的权限select 数据库所有者 ...
- Iaas-cloudstack概念
管理serverother high end ports tomcat20400 tomcat server.xml ...
- linux概念之/etc
[Thu Apr 02 15:04:32 1028 /dev/pts/0 192.168.2.250 /etc]#ll |grep -v "^d"|wc -l99[Thu Apr ...
- ASP.NET GridView HyperLinkField传值和取值【转】
来源:http://www.cnblogs.com/junjie94wan/archive/2011/08/17/2143623.html 经常做Winform程序,好久没有做WEB都有些生疏了,Gr ...
- CentOS6.5系统挂载NTFS分区的移动硬盘 centos安装repoforge源(yum)
CentOS6.5系统挂载NTFS分区的移动硬盘 作为IT的工作者,避免不了使用Linux系统,我现在使用的系统是CentOS6.5 X86_64位版本,但是插入NTFS移动硬盘没有办法识别.通过下面 ...