Micro template library A library for building device drivers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

327 lines
15 KiB

  1. /*!
  2. * \file TmetaTypelist.cpp
  3. *
  4. * Copyright (C) 2018 Christos Choutouridis
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as
  8. * published by the Free Software Foundation, either version 3
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include <utl/meta/meta.h>
  21. #include <gtest/gtest.h>
  22. #include <type_traits>
  23. namespace TmetaTypelist {
  24. using namespace utl;
  25. using namespace meta;
  26. /*
  27. * Types to behave like Fixtures
  28. */
  29. // Test type_of fixture
  30. template<class T> struct Identity {
  31. using type = T;
  32. };
  33. template<class T1, class T2> struct MfunBin {
  34. using type = int;
  35. };
  36. template<int a, int b> struct MfunBin_i {
  37. using type = int;
  38. };
  39. template<class T1> struct MfunUn1 {
  40. using type = int;
  41. };
  42. template<class T1> struct MfunUn2 {
  43. using type = int;
  44. };
  45. template <typename T> struct Pred_isInt {
  46. using type = std::is_integral<T>;
  47. };
  48. template <typename T> struct Pred_isVoid {
  49. using type = std::is_void<T>;
  50. };
  51. /*
  52. * Test high order metaFun tools
  53. */
  54. TEST(TmetaTypelist, Invoke) {
  55. using W = wrap <MfunBin>;
  56. using Wi = wrap_i<int, MfunBin_i>;
  57. using W1 = wrap<MfunUn1>;
  58. using W2 = wrap<MfunUn2>;
  59. using Q = quote<MfunBin>;
  60. using Qi = quote_i<int, MfunBin_i>;
  61. using Q1 = quote<MfunUn1>;
  62. using Q2 = quote<MfunUn2>;
  63. // identity
  64. EXPECT_EQ (true, (std::is_same<int, eval<identity<int>>>()));
  65. EXPECT_EQ (true, (std::is_same<int, identity_t<int>>()));
  66. EXPECT_EQ (true, (std::is_same<void*, identity_t<void*>>()));
  67. // invoke, check that invoke un-wraps and un-quotes staff
  68. EXPECT_EQ (true, (std::is_same< invoke<wrap<MfunBin>, int, char>, MfunBin<int, char> >()));
  69. EXPECT_EQ (true, (std::is_same< invoke<quote<MfunBin>, int, char>, MfunBin<int, char> >()));
  70. EXPECT_EQ (true, (std::is_same< invoke<wrap_i<int, MfunBin_i>, int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
  71. EXPECT_EQ (true, (std::is_same< invoke<quote_i<int, MfunBin_i>, int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
  72. // Wrap
  73. EXPECT_EQ (true, (std::is_same< wrap<MfunBin>::template apply<int, char>, MfunBin<int, char> >()));
  74. EXPECT_EQ (false, (std::is_same< wrap<MfunBin>::template apply<int, char>, MfunBin<int, int> >()));
  75. EXPECT_EQ (true, (std::is_same< wrap_i<int, MfunBin_i>::template apply<int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
  76. EXPECT_EQ (false, (std::is_same< wrap_i<int, MfunBin_i>::template apply<int_<7>, int_<42>>, MfunBin_i<42, 7> >()));
  77. // applicable trait
  78. EXPECT_EQ (true, (is_applicable_t<MfunBin, int, long>()));
  79. EXPECT_EQ (false, (is_applicable_t<MfunBin, int>()));
  80. EXPECT_EQ (true, (is_applicable_qt<Q, int, long>()));
  81. EXPECT_EQ (false, (is_applicable_qt<Q, int>()));
  82. EXPECT_EQ (true, (is_applicable_qt<W, int, long>()));
  83. EXPECT_EQ (false, (is_applicable_qt<W, int>()));
  84. EXPECT_EQ (true, (is_applicable_it<int, MfunBin_i, 7, 42>()));
  85. EXPECT_EQ (false, (is_applicable_it<int, MfunBin_i, 42>()));
  86. // defer
  87. EXPECT_EQ (true, (std::is_same<defer<MfunBin, int, void>::type, MfunBin<int, void>>()));
  88. EXPECT_EQ (true, (std::is_same<defer<MfunBin, void>::type, nil_>()));
  89. EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7, 42>::type, MfunBin_i<7, 42>>()));
  90. EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7>::type, nil_>()));
  91. // quote
  92. EXPECT_EQ (true, (std::is_same< quote<MfunBin>::template apply<int, void*>, MfunBin<int, void*> >()));
  93. EXPECT_EQ (false,(std::is_same< quote<MfunBin>::template apply<int, void*>, MfunBin<int, int> >()));
  94. EXPECT_EQ (true, (std::is_same< quote_i<int, MfunBin_i>::template apply< int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
  95. EXPECT_EQ (false,(std::is_same< quote_i<int, MfunBin_i>::template apply< int_<7>, int_<42>>, MfunBin_i<42, 7> >()));
  96. // compose
  97. EXPECT_EQ (true, (std::is_same<invoke<compose_f<MfunUn1>, int>, MfunUn1<int>>()));
  98. EXPECT_EQ (true, (std::is_same<invoke<compose_f<MfunUn1, MfunUn2>, int>, MfunUn1<MfunUn2<int>>>()));
  99. EXPECT_EQ (true, (std::is_same<invoke<compose<W1>, int>, MfunUn1<int>>()));
  100. EXPECT_EQ (true, (std::is_same<invoke<compose<W1, W2>, int>, MfunUn1<MfunUn2<int>>>()));
  101. EXPECT_EQ (true, (std::is_same<
  102. invoke<compose<W1, W2, Wi>, int_<7>, int_<42>>, MfunUn1<MfunUn2<MfunBin_i<7, 42>>>
  103. >()));
  104. EXPECT_EQ (true, (std::is_same<invoke<compose<Q1>, int>, MfunUn1<int>>()));
  105. EXPECT_EQ (true, (std::is_same<invoke<compose<Q1, Q2>, int>, MfunUn1<MfunUn2<int>>>()));
  106. EXPECT_EQ (true, (std::is_same<
  107. invoke<compose<Q1, Q2, Qi>, int_<7>, int_<42>>, MfunUn1<MfunUn2<MfunBin_i<7, 42>>>
  108. >()));
  109. // bind
  110. EXPECT_EQ (true, (std::is_same<invoke<bind_front<Q, int>, long>, MfunBin<int, long>>()));
  111. EXPECT_EQ (true, (std::is_same<invoke<bind_back<Q, int>, long>, MfunBin<long, int>>()));
  112. // Check the case of ill formed parameter composition. Quote must save us
  113. EXPECT_EQ (true, (std::is_same< nil_, invoke<Q, int> >()));
  114. EXPECT_EQ (true, (std::is_same< nil_, invoke<Qi, int_<42>> >()));
  115. EXPECT_EQ (true, (std::is_same< MfunUn1<MfunUn2<nil_>>, invoke<compose<Q1, Q2, Qi>, int_<42>> >()));
  116. }
  117. /*
  118. * Test typelist
  119. */
  120. TEST(TmetaTypelist, Basics) {
  121. using l1 = typelist<int, int, int>;
  122. using l2 = typelist<int, void*, int, void*>;
  123. using l3 = typelist<>;
  124. EXPECT_EQ (true, (std::is_same<l1, typelist<int>::times<3>>()));
  125. EXPECT_EQ (true, (std::is_same<l2, typelist<int, void*>::times<2>>()));
  126. EXPECT_EQ (true, (std::is_same<l3, typelist<>::times<3>>()));
  127. EXPECT_EQ (true, (std::is_same<l3, typelist<int>::times<0>>()));
  128. EXPECT_EQ (true, (std::is_same<l3, typelist<int, void>::times<0>>()));
  129. EXPECT_EQ (true, (std::is_same<typelist<short, double>, pair<short, double>>()));
  130. EXPECT_EQ (true, (std::is_same<l1, repeat <int_<3>, int>>()));
  131. EXPECT_EQ (true, (std::is_same<l2, repeat_c <2, int, void*>>()));
  132. EXPECT_EQ (3U, size<l1>());
  133. EXPECT_EQ (0U, size<l3>());
  134. EXPECT_EQ (true, empty<l3>());
  135. // pass typelist to an invocable
  136. EXPECT_EQ (true, (std::is_same< apply_t<quote<MfunUn1>, typelist<int>>, MfunUn1<int> >()));
  137. EXPECT_EQ (true, (std::is_same< apply_t<quote<MfunBin>, typelist<int, long>>, MfunBin<int, long> >()));
  138. }
  139. TEST(TmetaTypelist, ElementAccess) {
  140. using l = typelist<char*, void, void*, long, double, short>;
  141. EXPECT_EQ (true, (std::is_same<char*, at_c<l, 0>>()));
  142. EXPECT_EQ (true, (std::is_same<void*, at_c<l, 2>>()));
  143. EXPECT_EQ (true, (std::is_same<short, at_c<l, 5>>()));
  144. EXPECT_EQ (true, (std::is_same<nil_, at_c<l, 6>>()));
  145. EXPECT_EQ (true, (std::is_same<void, at<l, int_<1>>>()));
  146. EXPECT_EQ (true, (std::is_same<long, at<l, int_<3>>>()));
  147. EXPECT_EQ (true, (std::is_same<char*, front<l>>()));
  148. EXPECT_EQ (true, (std::is_same<short, back<l>>()));
  149. }
  150. TEST(TmetaTypelist, Concat) {
  151. using l1 = typelist<int, long, void>;
  152. using l2 = typelist<void*, int*>;
  153. using l3 = typelist<double, long double, short>;
  154. using l4 = typelist<>;
  155. using conc = typelist<int, long, void, void*, int*, double, long double, short>;
  156. EXPECT_EQ(true, (std::is_same<l4, cat<l4, l4>>()));
  157. EXPECT_EQ(true, (std::is_same<conc, cat<l1, l2, l3, l4>>()));
  158. EXPECT_EQ(true, (std::is_same<conc, cat<l1, l4, l2, l3>>()));
  159. EXPECT_EQ(true, (std::is_same<conc, cat<l4, l1, l2, l3>>()));
  160. }
  161. template<class T1, class T2> struct F {}; // binary invocable
  162. TEST(TmetaTypelist, Fold) {
  163. struct X1 {};
  164. struct X2 {};
  165. struct X3 {};
  166. struct X4 {};
  167. using Q = quote<F>;
  168. EXPECT_EQ(true, (std::is_same<fold<typelist<>, void, Q>, void>()));
  169. EXPECT_EQ(true, (std::is_same<fold<typelist<X1>, void, Q>, F<void, X1>>()));
  170. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2>, void, Q>, F<F<void, X1>, X2>>()));
  171. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3>, void, Q>, F<F<F<void, X1>, X2>, X3>>()));
  172. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3, X4>, void, Q>, F<F<F<F<void, X1>, X2>, X3>, X4>>()));
  173. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<>, void, Q>, void>()));
  174. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1>, void, Q>, F<X1, void>>()));
  175. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2>, void, Q>, F<X1, F<X2, void>>>()));
  176. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3>, void, Q>, F<X1, F<X2, F<X3, void>>>>()));
  177. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3, X4>, void, Q>, F<X1, F<X2, F<X3, F<X4, void>>>>>()));
  178. }
  179. TEST(TmetaTypelist, PushPopReverse) {
  180. using list = typelist <int, long, void>;
  181. using l_char = typelist <int, long, void, char>;
  182. using l_cc = typelist <int, long, void, char, char>;
  183. using char_l = typelist <char, int, long, void>;
  184. using cc_l = typelist<char, char, int, long, void>;
  185. using rev = typelist<void, long, int>;
  186. EXPECT_EQ (true, (std::is_same< char_l, push_front<list, char> >()));
  187. EXPECT_EQ (true, (std::is_same< cc_l, push_front<list, char, char> >()));
  188. EXPECT_EQ (true, (std::is_same< list, pop_front <char_l> >()));
  189. EXPECT_EQ (true, (std::is_same< l_char, push_back <list, char> >()));
  190. EXPECT_EQ (true, (std::is_same< l_cc, push_back <list, char, char> >()));
  191. EXPECT_EQ (true, (std::is_same< list, pop_back <l_char> >()));
  192. EXPECT_EQ (true, (std::is_same< rev, reverse <list> >()));
  193. }
  194. TEST(TmetaTypelist, Transform) {
  195. using QBin = quote<MfunBin>; // both metafuctions return int
  196. using QUn = quote<MfunUn1>;
  197. using l1 = typelist<char, int, float>;
  198. using l2 = typelist<void, void, void>;
  199. using r = typelist<int, int, int>;
  200. using r_ulazy = typelist <MfunUn1<char>, MfunUn1<int>, MfunUn1<float>>;
  201. using r_blazy = typelist <MfunBin<char, void>, MfunBin<int, void>, MfunBin<float, void>>;
  202. EXPECT_EQ (true, (std::is_same<r, transform<l1, QUn>>()));
  203. EXPECT_EQ (true, (std::is_same<r, transform<l1, l2, QBin>>()));
  204. EXPECT_EQ (true, (std::is_same<r_ulazy, transform_lazy<l1, QUn>>()));
  205. EXPECT_EQ (true, (std::is_same<r_blazy, transform_lazy<l1, l2, QBin>>()));
  206. }
  207. TEST(TmetaTypelist, Find) {
  208. using l1 = typelist <int, char, long, float>;
  209. using l2 = typelist <char, long, float>;
  210. using l3 = typelist <long, float>;
  211. using empty = typelist<>;
  212. EXPECT_EQ(true, (std::is_same<index_<1>, find_if<l1, same_as<char>>>()));
  213. EXPECT_EQ(true, (std::is_same<Npos, find_if<empty, same_as<char>>>()));
  214. EXPECT_EQ(true, (std::is_same<Npos, find_if<l1, same_as<double>>>()));
  215. EXPECT_EQ(true, (std::is_same<index_<2>, find<l1, long>>()));
  216. EXPECT_EQ(true, (std::is_same<l2, seek_if<l1, same_as<char>>>()));
  217. EXPECT_EQ(true, (std::is_same<empty, seek_if<empty, same_as<char>>>()));
  218. EXPECT_EQ(true, (std::is_same<empty, seek_if<l1, same_as<double>>>()));
  219. EXPECT_EQ(true, (std::is_same<l3, seek<l1, long>>()));
  220. }
  221. TEST(TmetaTypelist, Count) {
  222. using list = typelist<int, void*, char, int, long*, char, int, short>;
  223. using empty = typelist<>;
  224. EXPECT_EQ (true, (std::is_same<size_<3>, count_if<list, same_as<int>>>()));
  225. EXPECT_EQ (true, (std::is_same<size_<2>, count_if<list, same_as<char>>>()));
  226. EXPECT_EQ (true, (std::is_same<size_<0>, count_if<list, same_as<double>>>()));
  227. EXPECT_EQ (true, (std::is_same<size_<0>, count_if<empty, int>>()));
  228. EXPECT_EQ (true, (std::is_same<size_<1>, count<list, void*>>()));
  229. }
  230. TEST(TmetaTypelist, Filter) {
  231. using Q1 = quote<Pred_isInt>;
  232. using Q2 = quote<Pred_isVoid>;
  233. using list = typelist<int, float, char, long*, short, double, void*>;
  234. using filtered = typelist<int, char, short>;
  235. EXPECT_EQ (true, (std::is_same<filtered, filter<list, Q1>>()));
  236. EXPECT_EQ (true, (std::is_same<typelist<>, filter<typelist<>, Q1>>()));
  237. EXPECT_EQ (true, (std::is_same<typelist<>, filter<list, Q2>>()));
  238. EXPECT_EQ (true, (std::is_same<typelist<>, filter<typelist<>, Q1>>()));
  239. }
  240. TEST(TmetaTypelist, Replace) {
  241. using Q = quote<Pred_isInt>;
  242. using list = typelist<int, float, char, long*, short, double, void*>;
  243. using res = typelist<void,float, void, long*, void, double, void*>;
  244. using repl = typelist<int, float, void, long*, short, double, void*>;
  245. EXPECT_EQ (true, (std::is_same<res, replace_if<list, Q, void>>()));
  246. EXPECT_EQ (true, (std::is_same<typelist<>, replace_if<typelist<>, Q, void>>()));
  247. EXPECT_EQ (true, (std::is_same<res, replace_if<res, Q, void>>()));
  248. EXPECT_EQ (true, (std::is_same<typelist<>, replace_if<typelist<>, Q, void>>()));
  249. EXPECT_EQ (true, (std::is_same<repl, replace<list, char, void>>()));
  250. EXPECT_EQ (true, (std::is_same<typelist<>, replace<typelist<>, char, void>>()));
  251. }
  252. TEST (TmetaTypelist, AllAnyNone) {
  253. using l1 = typelist<int, float, char, long*, short, double, void*>;
  254. using l2 = typelist<int, char, long, short>;
  255. using l3 = typelist<>;
  256. EXPECT_EQ (true, (std::is_same<false_, all_of<l1, quote<Pred_isInt>>>()));
  257. EXPECT_EQ (true, (std::is_same<true_, all_of<l2, quote<Pred_isInt>>>()));
  258. EXPECT_EQ (true, (std::is_same<false_, all_of<l3, quote<Pred_isVoid>>>()));
  259. EXPECT_EQ (true, (std::is_same<true_, any_of<l1, quote<Pred_isInt>>>()));
  260. EXPECT_EQ (true, (std::is_same<false_, any_of<l2, quote<Pred_isVoid>>>()));
  261. EXPECT_EQ (true, (std::is_same<false_, any_of<l3, quote<Pred_isVoid>>>()));
  262. EXPECT_EQ (true, (std::is_same<true_, none_of<l1, quote<Pred_isVoid>>>()));
  263. EXPECT_EQ (true, (std::is_same<false_, none_of<l1, quote<Pred_isInt>>>()));
  264. EXPECT_EQ (true, (std::is_same<true_, none_of<l3, quote<Pred_isInt>>>()));
  265. }
  266. }