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.
 
 
 
 

394 lines
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 TestTypeOf {
  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_integral, Integreal_type_) {
  55. EXPECT_EQ(true, (std::is_same<int, type_<TestTypeOf<int>>>::value));
  56. }
  57. TEST(Tmeta_integral, IntegrealConstant) {
  58. EXPECT_EQ(true, (std::is_same<int, integral_constant<int, 42>::value_type>::value));
  59. EXPECT_EQ(true, (std::is_same<int, integral_constant<int, 42>::type::value_type>::value));
  60. EXPECT_EQ(42, (integral_constant<int, 0>::value_type(42)));
  61. EXPECT_EQ(42, (integral_constant<int, 42>()));
  62. }
  63. TEST(Tmeta_integral, 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_t_<0>::value_type>::value));
  89. EXPECT_EQ(42U, index_t_<42U>::value);
  90. EXPECT_EQ(true, (std::is_same<size_t, size_t_<0>::value_type>::value));
  91. EXPECT_EQ(42U, size_t_<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_integral, 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_logical, 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_logical, 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_logical, 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
  147. */
  148. TEST(Tmeta_void, 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, 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<type_<
  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_t_<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_t_<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_t_<3>, count_if<list, same_as<int>>>()));
  295. EXPECT_EQ (true, (std::is_same<size_t_<2>, count_if<list, same_as<char>>>()));
  296. EXPECT_EQ (true, (std::is_same<size_t_<0>, count_if<list, same_as<double>>>()));
  297. EXPECT_EQ (true, (std::is_same<size_t_<0>, count_if<empty, int>>()));
  298. EXPECT_EQ (true, (std::is_same<size_t_<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. }