Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

327 lignes
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. }