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彷佛只能使用函數來輸出了。spa

寫着寫着也發現本身的模板元編程的編碼和命名風格在不斷完善,果真要不停寫才能體會到東西。設計

(話說默認字體大小怎麼改啊,13px纔好看嘛)code

  1 template<typename T>
  2 struct ListGet;
  3 template<typename... TArgs>
  4 struct List;
  5 
  6 template<typename T, typename... TArgs>
  7 struct ListGet<List<T, TArgs...>>
  8 {
  9     using First = typename T;
 10     using Rest = List<TArgs...>;
 11 };
 12 
 13 template<typename... TArgs>
 14 struct List: ListGet<List<TArgs...>>
 15 {
 16     using Base = ListGet<List<TArgs...>>;
 17     using Self = List<TArgs...>;
 18 };
 19 
 20 template<typename T>
 21 struct ListIsEmpty;
 22 
 23 template<typename T, typename... TArgs>
 24 struct ListIsEmpty<List<T, TArgs...>>
 25 {
 26     using Result = Bool<false>;
 27 };
 28 template<>
 29 struct ListIsEmpty<List<>>
 30 {
 31     using Result = Bool<true>;
 32 };
 33 
 34 template<typename A, template<typename... Args> typename B>
 35 struct Change;
 36 
 37 template<template<typename... Args>typename A, template<typename... Args>typename B, typename... Args>
 38 struct Change<A<Args...>, B>
 39 {
 40     using Result = B<Args...>;
 41 };
 42 
 43 template<typename T1, typename T2>
 44 struct ListConnect;
 45 
 46 template<typename... TArgs1, typename... TArgs2>
 47 struct ListConnect<List<TArgs1...>, List<TArgs2...>>
 48 {
 49     using Result = typename List<TArgs1..., TArgs2...>;
 50 };
 51 template<typename T>
 52 struct ListReverse;
 53 
 54 template<typename... TArgs>
 55 struct ListReverse<List<TArgs...>>
 56 {
 57     using Param = typename List<TArgs...>;
 58     using Result = typename ListConnect<
 59         typename ListReverse<
 60             typename Param::Rest
 61         >::Result,
 62         typename List<typename Param::First>
 63     >::Result;
 64 };
 65 
 66 template<typename T>
 67 struct ListReverse<List<T>>
 68 {
 69     using Result = typename List<T>;
 70 };
 71 
 72 template<template<typename ST> typename TApplicative, typename T1>
 73 struct ListMap;
 74 
 75 template<template<typename ST> typename TApplicative, typename... TArgs>
 76 struct ListMap<TApplicative, List<TArgs...>>
 77 {
 78     using Param = typename List<TArgs...>;
 79     using Result = typename ListConnect<
 80         List<
 81             typename TApplicative<
 82                 typename Param::First
 83             >::Result
 84         >,
 85         typename ListMap<
 86             TApplicative,
 87             typename Param::Rest
 88         >::Result
 89     >::Result;
 90 };
 91 
 92 template<template<typename ST> typename TApplicative, typename TLast>
 93 struct ListMap<TApplicative, List<TLast>>
 94 {
 95     using Param = typename List<TLast>;
 96     using Result = typename List<typename TApplicative<TLast>::Result>;
 97 };
 98 
 99 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename T>
100 struct ListFoldLeft;
101 
102 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename... TArgs>
103 struct ListFoldLeft<TVal, TBinFunc, List<TArgs...>>
104 {
105     using Param = List<TArgs...>;
106     using Result = typename ListFoldLeft<
107         typename TBinFunc<
108             TVal,
109             typename Param::First
110         >::Result,
111         TBinFunc,
112         typename Param::Rest        
113     >::Result;
114 };
115 
116 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename TLast>
117 struct ListFoldLeft<TVal, TBinFunc, List<TLast>>
118 {
119     using Param = List<TLast>;
120     using Result = typename TBinFunc<TVal, typename Param::First>::Result;
121 };
122 
123 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename T>
124 struct ListScanLeft;
125 
126 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename... TArgs>
127 struct ListScanLeft<TVal, TBinFunc, List<TArgs...>>
128 {
129     using Param = List<TArgs...>;
130     using Value = typename TBinFunc<
131         TVal,
132         typename Param::First
133     >::Result;
134     using Result = typename ListConnect<
135         List<Value>,
136         typename ListScanLeft<
137             Value,
138             TBinFunc,
139             typename Param::Rest
140         >::Result
141     >::Result;
142 };
143 
144 template<typename TVal, template<typename TArg1, typename TArg2> typename TBinFunc, typename TLast>
145 struct ListScanLeft<TVal, TBinFunc, List<TLast>>
146 {
147     using Param = List<TLast>;
148     using Value = typename TBinFunc<
149         TVal,
150         typename Param::First
151     >::Result;
152     using Result = List<Value>;
153 };
154 
155 template<typename T, T V, typename... TRest>
156 void PrintList(List<PODType<T, V>, TRest...>)
157 {
158     std::cout << V << ' ';
159     PrintList(List<TRest...>());
160 }
161 
162 template<typename T, T V>
163 void PrintList(List<PODType<T, V>>)
164 {
165     std::cout << V;
166 }

(果真只有靜態高亮的C++代碼看上去就和翔同樣)blog

使用起來是這樣的繼承

1 List<Int<1>, Int<2>, Int<3>, Int<4>> list;
2 ListFoldLeft<Int<0>, Add, decltype(list)>::Result xxx;
3 ListScanLeft<Int<3>, Add, decltype(list)>::Result yyy;
4 PrintList(yyy);

foldl1,foldr,foldr1以及對應的scanr……啊啊啊啊啊啊啊啊啊ast

1 int main()
2 {
3     cout << L"我 整 個 人 都 遞 歸 了 ! ! ! ! ! ! 感 覺 自 己 充 滿 了 力 量 ! ! ! ! ! !「;
4     main();
5 }
相關文章
相關標籤/搜索