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.
 
 
 
 

395 lignes
16 KiB

  1. /*!
  2. * \file Tmeta.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 test_meta {
  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 integral constant
  53. */
  54. TEST(Tmeta, IntegrealType) {
  55. EXPECT_EQ(true, (std::is_same<int, eval<Identity<int>>>::value));
  56. }
  57. TEST(Tmeta, IntegrealConstant) {
  58. EXPECT_EQ(true, (std::is_same<int, integral_<int, 42>::value_type>::value));
  59. EXPECT_EQ(true, (std::is_same<int, integral_<int, 42>::type::value_type>::value));
  60. EXPECT_EQ(42, (integral_<int, 0>::value_type(42)));
  61. EXPECT_EQ(42, (integral_<int, 42>()));
  62. }
  63. TEST(Tmeta, BasicTypes) {
  64. EXPECT_EQ(true, (std::is_same<bool, bool_<false>::value_type>::value));
  65. EXPECT_EQ(true, bool_<true>::value);
  66. EXPECT_EQ(true, (std::is_same<bool, false_::value_type>::value));
  67. EXPECT_EQ(false, false_::value);
  68. EXPECT_EQ(true, (std::is_same<bool, true_::value_type>::value));
  69. EXPECT_EQ(true, true_::value);
  70. EXPECT_EQ(true, (std::is_same<int8_t, int8_<0>::value_type>::value));
  71. EXPECT_EQ(42, int8_<42>::value);
  72. EXPECT_EQ(true, (std::is_same<uint8_t, uint8_<0>::value_type>::value));
  73. EXPECT_EQ(42u, uint8_<42u>::value);
  74. EXPECT_EQ(true, (std::is_same<int16_t, int16_<0>::value_type>::value));
  75. EXPECT_EQ(42, int16_<42>::value);
  76. EXPECT_EQ(true, (std::is_same<uint16_t, uint16_<0>::value_type>::value));
  77. EXPECT_EQ(42u, uint16_<42u>::value);
  78. EXPECT_EQ(true, (std::is_same<int32_t, int32_<0>::value_type>::value));
  79. EXPECT_EQ(42, int32_<42>::value);
  80. EXPECT_EQ(true, (std::is_same<uint32_t, uint32_<0>::value_type>::value));
  81. EXPECT_EQ(42u, uint32_<42u>::value);
  82. EXPECT_EQ(true, (std::is_same<char, char_<0>::value_type>::value));
  83. EXPECT_EQ(42, char_<42>::value);
  84. EXPECT_EQ(true, (std::is_same<int, int_<0>::value_type>::value));
  85. EXPECT_EQ(42, int_<42>::value);
  86. EXPECT_EQ(true, (std::is_same<long, long_<0>::value_type>::value));
  87. EXPECT_EQ(42, long_<42>::value);
  88. EXPECT_EQ(true, (std::is_same<index_t, index_<0>::value_type>::value));
  89. EXPECT_EQ(42U, index_<42U>::value);
  90. EXPECT_EQ(true, (std::is_same<size_t, size_<0>::value_type>::value));
  91. EXPECT_EQ(42U, size_<42U>::value);
  92. EXPECT_EQ(sizeof(int), sizeof_<int>::value);
  93. EXPECT_EQ(alignof(int), alignof_<int>::value);
  94. EXPECT_EQ(static_cast<index_t>(-1), Npos::value);
  95. }
  96. /*
  97. * Test integral constant arithmetic operations
  98. */
  99. TEST(Tmeta, ArithmeticOperations) {
  100. EXPECT_EQ (int_<42>(), inc<int_<41>>());
  101. EXPECT_EQ (int_<42>(), dec<int_<43>>());
  102. EXPECT_EQ (int_<42>(), (add<int_<23>, add<int_<17>, int_<2>>>()));
  103. EXPECT_EQ (int_<42>(), (sub<int_<108>, int_<66>>()));
  104. EXPECT_EQ (int_<42>(), (mult<int_<7>, mult<int_<3>, int_<2>>>()));
  105. EXPECT_EQ (int_<42>(), (divide<int_<210>, int_<5>>()));
  106. EXPECT_EQ (int_<42>(), negate<int_<-42>>());
  107. EXPECT_EQ (int_< 1>(), (modulo<int_<43>, int_<42>>()));
  108. }
  109. /*
  110. * Test logical
  111. */
  112. TEST(Tmeta, ComparisonOperations) {
  113. EXPECT_EQ (true, (std::is_same<bool_<true>, not_c<false>>::value));
  114. EXPECT_EQ (true, (comp_eq<int_<7>, int_<7>>()));
  115. EXPECT_EQ (true, (comp_ne<int_<42>, int_<7>>()));
  116. EXPECT_EQ (true, (comp_lt<int_<42>, int_<43>>()));
  117. EXPECT_EQ (true, (comp_gt<int_<43>, int_<42>>()));
  118. EXPECT_EQ (true, (comp_le<int_<42>, int_<42>>()));
  119. EXPECT_EQ (true, (comp_ge<int_<42>, int_<42>>()));
  120. }
  121. TEST(Tmeta, BitOperations) {
  122. EXPECT_EQ (0x00, (bitand_<uint8_<0x55>, uint8_<0xAA>>()));
  123. EXPECT_EQ (0xFF, (bitor_ <uint8_<0x55>, uint8_<0xAA>>()));
  124. EXPECT_EQ (0xFA, (bitxor_<uint8_<0x55>, uint8_<0xAF>>()));
  125. EXPECT_EQ (0x00, (bitnot_<uint8_<-1>>()));
  126. EXPECT_EQ (0x04, (shift_left<uint8_<0x01>, uint8_<2>>()));
  127. EXPECT_EQ (0x00, (shift_left<uint8_<0x80>, uint8_<1>>()));
  128. EXPECT_EQ (0x02, (shift_right<uint8_<0x08>, uint8_<2>>()));
  129. EXPECT_EQ (0x00, (shift_right<uint8_<0x01>, uint8_<1>>()));
  130. }
  131. TEST(Tmeta, TypeOperations) {
  132. struct Foo {};
  133. struct Bar {};
  134. EXPECT_EQ (true, (std::is_same<bool_<true>, not_<bool_<false>>>()));
  135. EXPECT_EQ (true, (std::is_same<int_<42>, if_c<true, int_<42>, bool_<false>>>()));
  136. EXPECT_EQ (true, (std::is_same<int_<42>, if_<bool_<true>, int_<42>, bool_<false>>>()));
  137. EXPECT_EQ (true, (std::is_same<true_, or_<true_, false_>>()));
  138. EXPECT_EQ (true, (std::is_same<false_, or_<false_, false_>>()));
  139. EXPECT_EQ (true, (std::is_same<false_, and_<true_, false_>>()));
  140. EXPECT_EQ (true, (std::is_same<true_, and_<true_, true_>>()));
  141. EXPECT_EQ (true, (same_<Foo, Foo>()));
  142. EXPECT_EQ (false, (same_<Foo, Bar>()));
  143. EXPECT_EQ (true, (not_same_<Foo, Bar>()));
  144. }
  145. /*
  146. * Test void_t
  147. */
  148. TEST(Tmeta, VoidType) {
  149. struct Foo {};
  150. struct Bar {};
  151. EXPECT_EQ(true, (std::is_same<void, void_t<int, long, Foo, Bar>>()));
  152. }
  153. /*
  154. * Test invoke
  155. */
  156. TEST(Tmeta, Invoke) {
  157. using Q = quote<MfunBin>;
  158. using Qi = quote_i<int, MfunBin_i>;
  159. using Q1 = quote<MfunUn1>;
  160. using Q2 = quote<MfunUn2>;
  161. EXPECT_EQ (true, (std::is_same<int, identity_t<int>>()));
  162. EXPECT_EQ (true, (is_applicable_t<MfunBin, int, long>()));
  163. EXPECT_EQ (false, (is_applicable_t<MfunBin, int>()));
  164. EXPECT_EQ (true, (is_applicable_qt<Q, int, long>()));
  165. EXPECT_EQ (false, (is_applicable_qt<Q, int>()));
  166. EXPECT_EQ (true, (is_applicable_it<int, MfunBin_i, 7, 42>()));
  167. EXPECT_EQ (false, (is_applicable_it<int, MfunBin_i, 42>()));
  168. EXPECT_EQ (true, (std::is_same<defer<MfunBin, int, void>::type, MfunBin<int, void>>()));
  169. EXPECT_EQ (true, (std::is_same<defer<MfunBin, void>::type, nil_>()));
  170. EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7, 42>::type, MfunBin_i<7, 42>>()));
  171. EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7>::type, nil_>()));
  172. EXPECT_EQ (true, (std::is_same<invoke<Q, int>, nil_>()));
  173. EXPECT_EQ (true, (std::is_same<invoke<Q, int, void*>, MfunBin<int, void*>>()));
  174. EXPECT_EQ (true, (std::is_same<invoke<Qi, int_<7>, int_<42>>, MfunBin_i<7, 42>>()));
  175. EXPECT_EQ (true, (std::is_same<invoke<Qi, int_<42>>, nil_>()));
  176. EXPECT_EQ (true, (std::is_same<invoke<compose<Q1, Q2>, int>, MfunUn1<MfunUn2<int>>>()));
  177. EXPECT_EQ (true, (std::is_same<
  178. invoke<compose<Q1, Q2, Qi>, int_<7>, int_<42>>,
  179. MfunUn1<MfunUn2<MfunBin_i<7, 42>>>
  180. >()));
  181. EXPECT_EQ (true, (std::is_same<
  182. invoke<compose<Q1, Q2, Qi>, int_<42>>,
  183. MfunUn1<MfunUn2<nil_>>
  184. >()));
  185. EXPECT_EQ (true, (std::is_same<invoke<bind_front<Q, int>, long>, MfunBin<int, long>>()));
  186. EXPECT_EQ (true, (std::is_same<invoke<bind_back<Q, int>, long>, MfunBin<long, int>>()));
  187. }
  188. /*
  189. * Test typelist
  190. */
  191. TEST(Tmeta_typelist, Basics) {
  192. using l1 = typelist<int, int, int>;
  193. using l2 = typelist<int, void*, int, void*>;
  194. using l3 = typelist<>;
  195. EXPECT_EQ (true, (std::is_same<l1, typelist<int>::times<3>>()));
  196. EXPECT_EQ (true, (std::is_same<l2, typelist<int, void*>::times<2>>()));
  197. EXPECT_EQ (true, (std::is_same<l3, typelist<>::times<3>>()));
  198. EXPECT_EQ (true, (std::is_same<l3, typelist<int>::times<0>>()));
  199. EXPECT_EQ (true, (std::is_same<typelist<short, double>, pair<short, double>>()));
  200. EXPECT_EQ (true, (std::is_same<l1, repeat <int_<3>, int>>()));
  201. EXPECT_EQ (true, (std::is_same<l2, repeat_c <2, int, void*>>()));
  202. EXPECT_EQ (3, size<l1>());
  203. EXPECT_EQ (true, empty<l3>());
  204. // pass typelist to an invocable
  205. EXPECT_EQ (true, (std::is_same<eval<
  206. apply<quote<MfunBin>, typelist<int, long>>
  207. >,
  208. MfunBin<int, long>
  209. >()));
  210. }
  211. TEST(Tmeta_typelist, Element_access) {
  212. using l = typelist<char, void, long, double, short>;
  213. EXPECT_EQ (true, (std::is_same<char, at_c<l, 0>>()));
  214. EXPECT_EQ (true, (std::is_same<long, at_c<l, 2>>()));
  215. EXPECT_EQ (true, (std::is_same<nil_, at_c<l, 5>>()));
  216. EXPECT_EQ (true, (std::is_same<void, at<l, int_<1>>>()));
  217. EXPECT_EQ (true, (std::is_same<char, front<l>>()));
  218. EXPECT_EQ (true, (std::is_same<short, back<l>>()));
  219. }
  220. TEST(Tmeta_typelist, Concat) {
  221. using l1 = typelist<int, long, void>;
  222. using l2 = typelist<void*, int*>;
  223. using l3 = typelist<double, long double, short>;
  224. using l4 = typelist<>;
  225. using conc = typelist<int, long, void, void*, int*, double, long double, short>;
  226. EXPECT_EQ(true, (std::is_same<l4, cat<l4, l4>>()));
  227. EXPECT_EQ(true, (std::is_same<conc, cat<l1, l2, l3, l4>>()));
  228. EXPECT_EQ(true, (std::is_same<conc, cat<l1, l4, l2, l3>>()));
  229. EXPECT_EQ(true, (std::is_same<conc, cat<l4, l1, l2, l3>>()));
  230. }
  231. template<class T1, class T2> struct F {}; // binary invocable
  232. TEST(Tmeta_typelist, Fold) {
  233. struct X1 {};
  234. struct X2 {};
  235. struct X3 {};
  236. struct X4 {};
  237. using Q = quote<F>;
  238. EXPECT_EQ(true, (std::is_same<fold<typelist<>, void, Q>, void>()));
  239. EXPECT_EQ(true, (std::is_same<fold<typelist<X1>, void, Q>, F<void, X1>>()));
  240. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2>, void, Q>, F<F<void, X1>, X2>>()));
  241. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3>, void, Q>, F<F<F<void, X1>, X2>, X3>>()));
  242. EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3, X4>, void, Q>, F<F<F<F<void, X1>, X2>, X3>, X4>>()));
  243. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<>, void, Q>, void>()));
  244. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1>, void, Q>, F<X1, void>>()));
  245. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2>, void, Q>, F<X1, F<X2, void>>>()));
  246. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3>, void, Q>, F<X1, F<X2, F<X3, void>>>>()));
  247. EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3, X4>, void, Q>, F<X1, F<X2, F<X3, F<X4, void>>>>>()));
  248. }
  249. TEST(Tmeta_typelist, PushPopReverse) {
  250. using list = typelist <int, long, void>;
  251. using l_char = typelist <int, long, void, char>;
  252. using l_cc = typelist <int, long, void, char, char>;
  253. using char_l = typelist <char, int, long, void>;
  254. using cc_l = typelist<char, char, int, long, void>;
  255. using rev = typelist<void, long, int>;
  256. EXPECT_EQ (true, (std::is_same<char_l, push_front<list, char>>()));
  257. EXPECT_EQ (true, (std::is_same<cc_l, push_front<list, char, char>>()));
  258. EXPECT_EQ (true, (std::is_same<list, pop_front <char_l>>()));
  259. EXPECT_EQ (true, (std::is_same<l_char, push_back <list, char>>()));
  260. EXPECT_EQ (true, (std::is_same<l_cc, push_back <list, char, char>>()));
  261. EXPECT_EQ (true, (std::is_same<list, pop_back <l_char>>()));
  262. EXPECT_EQ (true, (std::is_same<rev, reverse <list>>()));
  263. }
  264. TEST(Tmeta_typelist, Transform) {
  265. using QBin = quote<MfunBin>;
  266. using QUn = quote<MfunUn1>;
  267. using l1 = typelist<char, int, float>;
  268. using l2 = typelist<void, void, void>;
  269. using r = typelist<int, int, int>;
  270. using r_ulazy = typelist <MfunUn1<char>, MfunUn1<int>, MfunUn1<float>>;
  271. using r_blazy = typelist <MfunBin<char, void>, MfunBin<int, void>, MfunBin<float, void>>;
  272. EXPECT_EQ (true, (std::is_same<r, transform<l1, QUn>>()));
  273. EXPECT_EQ (true, (std::is_same<r, transform<l1, l2, QBin>>()));
  274. EXPECT_EQ (true, (std::is_same<r_ulazy, transform_lazy<l1, QUn>>()));
  275. EXPECT_EQ (true, (std::is_same<r_blazy, transform_lazy<l1, l2, QBin>>()));
  276. }
  277. TEST(Tmeta_typelist, Find) {
  278. using l1 = typelist <int, char, long, float>;
  279. using l2 = typelist <char, long, float>;
  280. using l3 = typelist <long, float>;
  281. using empty = typelist<>;
  282. EXPECT_EQ(true, (std::is_same<index_<1>, find_if<l1, same_as<char>>>()));
  283. EXPECT_EQ(true, (std::is_same<Npos, find_if<empty, same_as<char>>>()));
  284. EXPECT_EQ(true, (std::is_same<Npos, find_if<l1, same_as<double>>>()));
  285. EXPECT_EQ(true, (std::is_same<index_<2>, find<l1, long>>()));
  286. EXPECT_EQ(true, (std::is_same<l2, seek_if<l1, same_as<char>>>()));
  287. EXPECT_EQ(true, (std::is_same<empty, seek_if<empty, same_as<char>>>()));
  288. EXPECT_EQ(true, (std::is_same<empty, seek_if<l1, same_as<double>>>()));
  289. EXPECT_EQ(true, (std::is_same<l3, seek<l1, long>>()));
  290. }
  291. TEST(Tmeta_typelist, Count) {
  292. using list = typelist<int, void*, char, int, long*, char, int, short>;
  293. using empty = typelist<>;
  294. EXPECT_EQ (true, (std::is_same<size_<3>, count_if<list, same_as<int>>>()));
  295. EXPECT_EQ (true, (std::is_same<size_<2>, count_if<list, same_as<char>>>()));
  296. EXPECT_EQ (true, (std::is_same<size_<0>, count_if<list, same_as<double>>>()));
  297. EXPECT_EQ (true, (std::is_same<size_<0>, count_if<empty, int>>()));
  298. EXPECT_EQ (true, (std::is_same<size_<1>, count<list, void*>>()));
  299. }
  300. TEST(Tmeta_typelist, Filter) {
  301. using Q1 = quote<Pred_isInt>;
  302. using Q2 = quote<Pred_isVoid>;
  303. using list = typelist<int, float, char, long*, short, double, void*>;
  304. using filtered = typelist<int, char, short>;
  305. EXPECT_EQ (true, (std::is_same<filtered, filter<list, Q1>>()));
  306. EXPECT_EQ (true, (std::is_same<typelist<>, filter<typelist<>, Q1>>()));
  307. EXPECT_EQ (true, (std::is_same<typelist<>, filter<list, Q2>>()));
  308. }
  309. TEST(Tmeta_typelist, Replace) {
  310. using Q = quote<Pred_isInt>;
  311. using list = typelist<int, float, char, long*, short, double, void*>;
  312. using res = typelist<void,float, void, long*, void, double, void*>;
  313. using repl = typelist<int, float, void, long*, short, double, void*>;
  314. EXPECT_EQ (true, (std::is_same<res, replace_if<list, Q, void>>()));
  315. EXPECT_EQ (true, (std::is_same<typelist<>, replace_if<typelist<>, Q, void>>()));
  316. EXPECT_EQ (true, (std::is_same<res, replace_if<res, Q, void>>()));
  317. EXPECT_EQ (true, (std::is_same<repl, replace<list, char, void>>()));
  318. }
  319. TEST (Tmeta_typelist, AllAnyNone) {
  320. using l1 = typelist<int, float, char, long*, short, double, void*>;
  321. using l2 = typelist<int, char, long, short>;
  322. EXPECT_EQ (true, (std::is_same<false_, all_of<l1, quote<Pred_isInt>>>()));
  323. EXPECT_EQ (true, (std::is_same<true_, all_of<l2, quote<Pred_isInt>>>()));
  324. EXPECT_EQ (true, (std::is_same<true_, any_of<l1, quote<Pred_isInt>>>()));
  325. EXPECT_EQ (true, (std::is_same<false_, any_of<l2, quote<Pred_isVoid>>>()));
  326. EXPECT_EQ (true, (std::is_same<true_, none_of<l1, quote<Pred_isVoid>>>()));
  327. EXPECT_EQ (true, (std::is_same<false_, none_of<l1, quote<Pred_isInt>>>()));
  328. }
  329. }