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.
 
 
 
 

423 lines
17 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/concepts/concepts.h>
  21. #include <utl/meta/meta.h>
  22. #include <gtest/gtest.h>
  23. namespace test_concepts {
  24. using namespace utl;
  25. /*
  26. * Fixture like types
  27. */
  28. struct Empty { };
  29. struct HaveOnlyCopy {
  30. HaveOnlyCopy(const HaveOnlyCopy&) = default;
  31. HaveOnlyCopy(HaveOnlyCopy&&) = delete;
  32. HaveOnlyCopy& operator= (const HaveOnlyCopy&) = default;
  33. HaveOnlyCopy& operator= (HaveOnlyCopy&&) = delete;
  34. };
  35. struct HaveOnlyMove {
  36. HaveOnlyMove(const HaveOnlyMove&) = delete;
  37. HaveOnlyMove(HaveOnlyMove&&) = default;
  38. HaveOnlyMove& operator= (const HaveOnlyMove&) = delete;
  39. HaveOnlyMove& operator= (HaveOnlyMove&&) = default;
  40. };
  41. struct HaveCopyAndMove {
  42. HaveCopyAndMove(const HaveCopyAndMove&) = default;
  43. HaveCopyAndMove(HaveCopyAndMove&&) = default;
  44. HaveCopyAndMove& operator= (const HaveCopyAndMove&) = default;
  45. HaveCopyAndMove& operator= (HaveCopyAndMove&&) = default;
  46. };
  47. class HavePerfectForwarding {
  48. public: template<class T> HavePerfectForwarding(T&&) { }
  49. };
  50. class Base { };
  51. class Derived1 : public Base { };
  52. class Derived2 : public Derived1 { };
  53. class HaveOperatorBase {
  54. public: operator Base() { return base; }
  55. Base base;
  56. };
  57. struct A {
  58. int a_;
  59. public:
  60. A(int a =0) : a_{a} { };
  61. A(const A&) = default;
  62. A(A&&) = default;
  63. };
  64. bool operator== (const A& l, const A& r) { return l.a_ == r.a_; }
  65. bool operator!= (const A& l, const A& r) { return l.a_ != r.a_; }
  66. struct B {
  67. int b_;
  68. public:
  69. B(int b =0) : b_{b} { };
  70. B(const B&) = default;
  71. B(B&&) = default;
  72. B& operator= (const B&) = default;
  73. B& operator= (B&&) = default;
  74. };
  75. bool operator== (const B& l, const B& r) { return l.b_ == r.b_; }
  76. bool operator!= (const B& l, const B& r) { return l.b_ != r.b_; }
  77. bool operator< (const B& l, const B& r) { return l.b_ < r.b_; }
  78. bool operator<= (const B& l, const B& r) { return l.b_ <= r.b_; }
  79. bool operator> (const B& l, const B& r) { return l.b_ > r.b_; }
  80. bool operator>= (const B& l, const B& r) { return l.b_ >= r.b_; }
  81. TEST(TConcepts, Same) {
  82. // Same
  83. EXPECT_EQ (true, (Same<int, int>));
  84. EXPECT_EQ (false, (Same<int, long>));
  85. EXPECT_EQ (true, (Same<int*, int*>));
  86. EXPECT_EQ (true, (Same<double&, double&>));
  87. EXPECT_EQ (false, (Same<int, Empty>));
  88. EXPECT_EQ (false, (Same<Base, Derived1>));
  89. }
  90. TEST(TConcepts, DerivedFrom) {
  91. // DerivedFrom
  92. EXPECT_EQ (true, (DerivedFrom<Derived1, Base>));
  93. EXPECT_EQ (true, (DerivedFrom<Derived2, Derived1>));
  94. EXPECT_EQ (true, (DerivedFrom<Derived2, Base>));
  95. EXPECT_EQ (false, (DerivedFrom<Base, Derived1>));
  96. EXPECT_EQ (false, (DerivedFrom<Base, int>));
  97. EXPECT_EQ (false, (DerivedFrom<void, int>));
  98. }
  99. TEST(TConcepts, ConvertibleTo) {
  100. // ConvertibleTo
  101. EXPECT_EQ (true, (ConvertibleTo<void, void>));
  102. EXPECT_EQ (false, (ConvertibleTo<Base, void>));
  103. EXPECT_EQ (false, (ConvertibleTo<Base*, Derived1*>));
  104. EXPECT_EQ (true, (ConvertibleTo<Derived1*, Base*>));
  105. EXPECT_EQ (true, (ConvertibleTo<HaveOperatorBase, Base>));
  106. EXPECT_EQ (true, (ConvertibleTo<Base, HavePerfectForwarding>));
  107. }
  108. TEST(TConcepts, CommonReference) {
  109. // CommonReference
  110. EXPECT_EQ (true, (CommonReference<Derived1, Base>));
  111. EXPECT_EQ (true, (CommonReference<Derived1&, Base>));
  112. EXPECT_EQ (true, (CommonReference<const Empty&&, const Empty&>));
  113. EXPECT_EQ (false, (CommonReference<Empty&, const volatile Empty&>));
  114. //FIXME: CommonReference needs SFINAE friendly implementation
  115. //EXPECT_EQ (false, (CommonReference<Empty&&, const volatile Empty&>)); <- yields compiler error
  116. // Common
  117. EXPECT_EQ (true, (Common<int, int>));
  118. EXPECT_EQ (true, (Common<Base, Derived1>));
  119. EXPECT_EQ (true, (Common<Derived1, Derived2>));
  120. EXPECT_EQ (true, (Common<Base, HaveOperatorBase>));
  121. EXPECT_EQ (true, (Common<Base, HavePerfectForwarding>));
  122. }
  123. TEST(TConcepts, Integral) {
  124. // Integral
  125. EXPECT_EQ (false, (Integral<void>));
  126. EXPECT_EQ (true, (Integral<int>));
  127. EXPECT_EQ (true, (Integral<bool>));
  128. EXPECT_EQ (false, (Integral<int*>));
  129. EXPECT_EQ (false, (Integral<Base>));
  130. EXPECT_EQ (true, (Integral<meta::int_<42>::value_type>));
  131. EXPECT_EQ (false, (Integral<meta::int_<42>::type>));
  132. // SignedIntegral
  133. EXPECT_EQ (false, (SignedIntegral<void>));
  134. EXPECT_EQ (true, (SignedIntegral<int>));
  135. EXPECT_EQ (false, (SignedIntegral<int*>));
  136. EXPECT_EQ (false, (SignedIntegral<unsigned long>));
  137. EXPECT_EQ (false, (SignedIntegral<double>));
  138. EXPECT_EQ (false, (SignedIntegral<Base>));
  139. EXPECT_EQ (true, (SignedIntegral<meta::int16_<42>::value_type>));
  140. // UnsignedIntegral
  141. EXPECT_EQ (false, (UnsignedIntegral<void>));
  142. EXPECT_EQ (true, (UnsignedIntegral<unsigned int>));
  143. EXPECT_EQ (false, (UnsignedIntegral<long>));
  144. EXPECT_EQ (false, (UnsignedIntegral<double>));
  145. EXPECT_EQ (false, (UnsignedIntegral<Base>));
  146. EXPECT_EQ (true, (UnsignedIntegral<meta::uint16_<42>::value_type>));
  147. }
  148. TEST(TConcepts, Assignable) {
  149. // MoveAssignable
  150. EXPECT_EQ (false, (MoveAssignable<void>));
  151. EXPECT_EQ (true, (MoveAssignable<void*>));
  152. EXPECT_EQ (true, (MoveAssignable<int>));
  153. EXPECT_EQ (true, (MoveAssignable<int*>));
  154. EXPECT_EQ (false, (MoveAssignable<HaveOnlyCopy>));
  155. EXPECT_EQ (true, (MoveAssignable<HaveOnlyMove>));
  156. EXPECT_EQ (true, (MoveAssignable<HaveCopyAndMove>));
  157. EXPECT_EQ (true, (MoveAssignable<Empty>));
  158. EXPECT_EQ (true, (MoveAssignable<HavePerfectForwarding>));
  159. // CopyAssignable
  160. EXPECT_EQ (false, (CopyAssignable<void>));
  161. EXPECT_EQ (true, (CopyAssignable<void*>));
  162. EXPECT_EQ (true, (CopyAssignable<int>));
  163. EXPECT_EQ (true, (CopyAssignable<int*>));
  164. EXPECT_EQ (true, (CopyAssignable<HaveOnlyCopy>));
  165. EXPECT_EQ (false, (CopyAssignable<HaveOnlyMove>));
  166. EXPECT_EQ (true, (CopyAssignable<HaveCopyAndMove>));
  167. EXPECT_EQ (true, (CopyAssignable<Empty>));
  168. EXPECT_EQ (true, (CopyAssignable<HavePerfectForwarding>));
  169. // Assignable
  170. EXPECT_EQ (false, (Assignable<void, void>));
  171. EXPECT_EQ (false, (Assignable<int&, void>));
  172. EXPECT_EQ (true, (Assignable<int&, int>));
  173. EXPECT_EQ (false, (Assignable<int, int>));
  174. EXPECT_EQ (false, (Assignable<int*, int*>));
  175. EXPECT_EQ (true, (Assignable<Base&, Derived1>));
  176. EXPECT_EQ (false, (Assignable<Derived1&, Base>));
  177. EXPECT_EQ (true, (Assignable<HaveOnlyMove&, HaveOnlyMove&&>));
  178. EXPECT_EQ (true , (Assignable<HaveOnlyMove&, HaveOnlyMove>));
  179. EXPECT_EQ (true, (Assignable<Empty&, Empty>));
  180. }
  181. TEST(TConcepts, Swappable) {
  182. // Swappable, SwappableWith
  183. EXPECT_EQ (false, (Swappable<void>));
  184. EXPECT_EQ (true, (Swappable<void*>));
  185. EXPECT_EQ (true, (Swappable<int>));
  186. EXPECT_EQ (true, (Swappable<Base>));
  187. EXPECT_EQ (true, (SwappableWith<int, int>));
  188. EXPECT_EQ (false, (SwappableWith<int, Base>));
  189. EXPECT_EQ (false, (SwappableWith<Base, Derived1>));
  190. // Destructible
  191. EXPECT_EQ (false, (Destructible<void>));
  192. EXPECT_EQ (true, (Destructible<void*>));
  193. EXPECT_EQ (true, (Destructible<int>));
  194. EXPECT_EQ (true, (Destructible<int&>));
  195. EXPECT_EQ (true, (Destructible<Base>));
  196. EXPECT_EQ (true, (Destructible<HavePerfectForwarding>));
  197. }
  198. TEST(TConcepts, Constructible) {
  199. // Constructible
  200. EXPECT_EQ (false, (Constructible<void>));
  201. EXPECT_EQ (true, (Constructible<void*>));
  202. EXPECT_EQ (true, (Constructible<Base>));
  203. EXPECT_EQ (false, (Constructible<HaveOnlyMove>));
  204. EXPECT_EQ (true, (Constructible<HavePerfectForwarding, int>));
  205. // DefaultConstructible
  206. EXPECT_EQ (false, (DefaultConstructible<void>));
  207. EXPECT_EQ (true, (DefaultConstructible<void*>));
  208. EXPECT_EQ (false, (DefaultConstructible<int&>));
  209. EXPECT_EQ (true, (DefaultConstructible<Base>));
  210. EXPECT_EQ (true, (DefaultConstructible<Derived1>));
  211. EXPECT_EQ (false, (DefaultConstructible<HaveOnlyCopy>));
  212. EXPECT_EQ (false, (DefaultConstructible<HaveOnlyMove>));
  213. EXPECT_EQ (false, (DefaultConstructible<HavePerfectForwarding>));
  214. // MoveConstructible
  215. EXPECT_EQ (false, (MoveConstructible<void>));
  216. EXPECT_EQ (true, (MoveConstructible<void*>));
  217. EXPECT_EQ (true, (MoveConstructible<Base>));
  218. EXPECT_EQ (true, (MoveConstructible<Derived1>));
  219. EXPECT_EQ (true, (MoveConstructible<HaveOnlyMove>));
  220. EXPECT_EQ (false, (MoveConstructible<HaveOnlyCopy>));
  221. EXPECT_EQ (true, (MoveConstructible<HaveCopyAndMove>));
  222. EXPECT_EQ (true , (MoveConstructible<HavePerfectForwarding>));
  223. // CopyConstructible
  224. EXPECT_EQ (false, (CopyConstructible<void>));
  225. EXPECT_EQ (true, (CopyConstructible<void*>));
  226. EXPECT_EQ (true, (CopyConstructible<Base>));
  227. EXPECT_EQ (true, (CopyConstructible<Derived1>));
  228. EXPECT_EQ (false, (CopyConstructible<HaveOnlyMove>));
  229. EXPECT_EQ (false, (CopyConstructible<HaveOnlyCopy>));
  230. EXPECT_EQ (true, (CopyConstructible<HaveCopyAndMove>));
  231. EXPECT_EQ (true , (CopyConstructible<HavePerfectForwarding>));
  232. }
  233. TEST(TConcepts, MovableCopyable) {
  234. // Movable
  235. EXPECT_EQ (false, (Movable<void>));
  236. EXPECT_EQ (true, (Movable<int>));
  237. EXPECT_EQ (true, (Movable<Base>));
  238. EXPECT_EQ (true, (Movable<Derived1>));
  239. EXPECT_EQ (true, (Movable<HaveOnlyMove>));
  240. EXPECT_EQ (false, (Movable<HaveOnlyCopy>));
  241. EXPECT_EQ (true, (Movable<HaveCopyAndMove>));
  242. EXPECT_EQ (true , (Movable<HavePerfectForwarding>));
  243. // Copyable
  244. EXPECT_EQ (false, (Copyable<void>));
  245. EXPECT_EQ (true, (Copyable<int>));
  246. EXPECT_EQ (true, (Copyable<Base>));
  247. EXPECT_EQ (true, (Copyable<Derived1>));
  248. EXPECT_EQ (false, (Copyable<HaveOnlyMove>));
  249. EXPECT_EQ (false, (Copyable<HaveOnlyCopy>));
  250. EXPECT_EQ (true, (Copyable<HaveCopyAndMove>));
  251. EXPECT_EQ (true , (Copyable<HavePerfectForwarding>));
  252. }
  253. TEST(TConcepts, Boolean) {
  254. // Boolean
  255. EXPECT_EQ (false, (Boolean<void>));
  256. EXPECT_EQ (true, (Boolean<bool>));
  257. EXPECT_EQ (true, (Boolean<int>));
  258. EXPECT_EQ (true, (Boolean<double>));
  259. EXPECT_EQ (true, (Boolean<std::true_type>));
  260. EXPECT_EQ (true, (Boolean<meta::true_>));
  261. EXPECT_EQ (false, (Boolean<Empty>));
  262. }
  263. TEST(TConcepts, Comparable) {
  264. // EqualityComparable
  265. EXPECT_EQ (false, (EqualityComparable<void>));
  266. EXPECT_EQ (true, (EqualityComparable<bool>));
  267. EXPECT_EQ (true, (EqualityComparable<int>));
  268. EXPECT_EQ (false, (EqualityComparable<Empty>));
  269. EXPECT_EQ (true, (EqualityComparable<A>));
  270. // EqualityComparableWith
  271. EXPECT_EQ (false, (EqualityComparableWith<void, bool>));
  272. EXPECT_EQ (false, (EqualityComparableWith<void, void>));
  273. EXPECT_EQ (true, (EqualityComparableWith<bool, bool>));
  274. EXPECT_EQ (true, (EqualityComparableWith<int, int>));
  275. EXPECT_EQ (true, (EqualityComparableWith<int, bool>));
  276. EXPECT_EQ (false, (EqualityComparableWith<Empty, Empty>));
  277. EXPECT_EQ (false, (EqualityComparableWith<int, Empty>));
  278. EXPECT_EQ (true, (EqualityComparableWith<A, A>));
  279. EXPECT_EQ (false, (EqualityComparableWith<A, B>));
  280. // StrictTotallyOrdered
  281. EXPECT_EQ (false, (StrictTotallyOrdered<void>));
  282. EXPECT_EQ (true, (StrictTotallyOrdered<bool>));
  283. EXPECT_EQ (true, (StrictTotallyOrdered<int>));
  284. EXPECT_EQ (true, (StrictTotallyOrdered<double>));
  285. EXPECT_EQ (false, (StrictTotallyOrdered<Empty>));
  286. EXPECT_EQ (false, (StrictTotallyOrdered<A>));
  287. EXPECT_EQ (true, (StrictTotallyOrdered<B>));
  288. // StrictTotallyOrderedWith
  289. EXPECT_EQ (false, (StrictTotallyOrderedWith<void, void>));
  290. EXPECT_EQ (false, (StrictTotallyOrderedWith<int, void>));
  291. EXPECT_EQ (true, (StrictTotallyOrderedWith<bool, bool>));
  292. EXPECT_EQ (true, (StrictTotallyOrderedWith<int, double>));
  293. EXPECT_EQ (false, (StrictTotallyOrderedWith<int, Empty>));
  294. EXPECT_EQ (false, (StrictTotallyOrderedWith<Base, Derived1>));
  295. EXPECT_EQ (false, (StrictTotallyOrderedWith<A, A>));
  296. EXPECT_EQ (true, (StrictTotallyOrderedWith<B, B>));
  297. EXPECT_EQ (false, (StrictTotallyOrderedWith<A, B>));
  298. }
  299. TEST(TConcepts, Types) {
  300. // Semiregular
  301. EXPECT_EQ (false, (Semiregular<void>));
  302. EXPECT_EQ (true, (Semiregular<int>));
  303. EXPECT_EQ (true, (Semiregular<Empty>));
  304. EXPECT_EQ (false, (Semiregular<HaveOnlyMove>));
  305. EXPECT_EQ (false, (Semiregular<HaveOnlyCopy>));
  306. EXPECT_EQ (false, (Semiregular<HaveCopyAndMove>));
  307. EXPECT_EQ (false, (Semiregular<A>));
  308. EXPECT_EQ (true, (Semiregular<B>));
  309. // Regular
  310. EXPECT_EQ (false, (Regular<void>));
  311. EXPECT_EQ (true, (Regular<int>));
  312. EXPECT_EQ (true, (Regular<int*>));
  313. EXPECT_EQ (false, (Regular<Empty>));
  314. EXPECT_EQ (false, (Regular<HaveOnlyMove>));
  315. EXPECT_EQ (false, (Regular<HaveOnlyCopy>));
  316. EXPECT_EQ (false, (Regular<HaveCopyAndMove>));
  317. EXPECT_EQ (false, (Regular<A>));
  318. EXPECT_EQ (true, (Regular<B>));
  319. // Scalar
  320. EXPECT_EQ (false, (Scalar<void>));
  321. EXPECT_EQ (true, (Scalar<int>));
  322. EXPECT_EQ (true, (Scalar<long*>));
  323. EXPECT_EQ (false, (Scalar<A>));
  324. EXPECT_EQ (false, (Scalar<B>));
  325. // Arithmetic
  326. EXPECT_EQ (false, (Arithmetic<void>));
  327. EXPECT_EQ (true, (Arithmetic<int>));
  328. EXPECT_EQ (false, (Arithmetic<long*>));
  329. EXPECT_EQ (false, (Arithmetic<A>));
  330. EXPECT_EQ (false, (Arithmetic<B>));
  331. // FloatingPoint
  332. EXPECT_EQ (false, (FloatingPoint<void>));
  333. EXPECT_EQ (true, (FloatingPoint<float>));
  334. EXPECT_EQ (true, (FloatingPoint<double>));
  335. EXPECT_EQ (false, (FloatingPoint<int>));
  336. EXPECT_EQ (false, (FloatingPoint<float*>));
  337. EXPECT_EQ (false, (FloatingPoint<A>));
  338. EXPECT_EQ (false, (FloatingPoint<B>));
  339. }
  340. struct Inv {
  341. void operator() (int) { };
  342. void operator() () { };
  343. };
  344. struct Pred {
  345. bool operator () (int) { return true; }
  346. bool operator () (int, int) { return true; }
  347. };
  348. TEST(TConcepts, Callable) {
  349. EXPECT_EQ (true, (Invocable<Inv, int>));
  350. EXPECT_EQ (true, (Invocable<Inv>));
  351. EXPECT_EQ (true, (Invocable<Inv, double>));
  352. EXPECT_EQ (false, (Invocable<Inv, Empty>));
  353. EXPECT_EQ (true, (RegularInvocable<Inv, int>));
  354. EXPECT_EQ (false, (Predicate<Inv, int>));
  355. EXPECT_EQ (true, (Predicate<Pred, int>));
  356. EXPECT_EQ (false, (Predicate<Pred, Empty>));
  357. EXPECT_EQ (true, (Relation<Pred, int, int>));
  358. EXPECT_EQ (true, (Relation<Pred, int, double>));
  359. EXPECT_EQ (false, (Relation<Pred, Empty, int>));
  360. EXPECT_EQ (true, (StrictWeakOrder<Pred, int, int>));
  361. EXPECT_EQ (false, (StrictWeakOrder<Pred, int, Empty>));
  362. }
  363. struct Incr {
  364. Incr& operator++() { return *this; }
  365. Incr operator++(int) { return *this; }
  366. };
  367. int type_printer (int* i) { return *i; }
  368. TEST(TConcepts, Iterators) {
  369. // type_printer(detail::try_ppI<Incr&>{});
  370. // type_printer(detail::try_Ipp<Incr&>{});
  371. // type_printer(meta::detected_t<detail::try_ppI, int>{});
  372. EXPECT_EQ (true, (WeaklyIncrementable<int>));
  373. EXPECT_EQ (false, (WeaklyIncrementable<void>));
  374. EXPECT_EQ (false, (WeaklyIncrementable<meta::nil_>));
  375. EXPECT_EQ (true, (WeaklyIncrementable<Incr>));
  376. EXPECT_EQ (false, (WeaklyIncrementable<Incr&>));
  377. }
  378. }