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.
 
 
 
 

162 lines
7.5 KiB

  1. /*!
  2. * \file TmetaDetection.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 TmetaDetection {
  24. using namespace utl;
  25. using namespace meta;
  26. /*
  27. * Types to behave like Fixtures
  28. */
  29. struct Foo {};
  30. struct Bar {};
  31. template <typename T> struct A {
  32. using type = T; // nested type
  33. A(int i, double d) : i_(i), d_(d) {} // declare a non-trivial constructor
  34. A& operator++() { ++i_; return *this; } // declare an operator
  35. // A sfinae function
  36. template <typename TT = T, typename = when<std::is_integral<TT>::type::value>>
  37. TT sfun () { return TT{}; }
  38. private:
  39. int i_; double d_;
  40. };
  41. // A binary metafunction
  42. template <typename T1, typename T2>
  43. struct mFun {
  44. using type = std::is_same <T1, T2>;
  45. };
  46. // detectors
  47. template <typename T> using try_type = typename T::type;
  48. template <typename T> using try_none = typename T::none;
  49. template <typename T> using try_ctor1= decltype (T(std::declval<int>(), std::declval<double>()));
  50. template <typename T> using try_ctor2= decltype (T(std::declval<int>()));
  51. template <typename T> using try_ppT = decltype (++(std::declval<T>()));
  52. template <typename T> using try_Tpp = decltype (std::declval<T>()++);
  53. template <typename T> using try_sfun = decltype (std::declval<T>().sfun());
  54. /*
  55. * void_t
  56. */
  57. TEST(TmetaDetection, VoidType) {
  58. EXPECT_EQ(true, (std::is_same<void, void_t<int, long, void*, void, Foo, Bar>>()));
  59. EXPECT_EQ(true, (std::is_same<void, void_t<>>()));
  60. }
  61. /*
  62. * not a type
  63. */
  64. TEST(TmetaDetection, NotAType) {
  65. EXPECT_EQ(false, (std::is_default_constructible<nat_>()));
  66. EXPECT_EQ(false, (std::is_destructible<nat_>()));
  67. EXPECT_EQ(false, (std::is_copy_constructible<nat_>()));
  68. EXPECT_EQ(false, (std::is_copy_assignable<nat_>()));
  69. }
  70. /*
  71. * Idiom
  72. */
  73. TEST(TmetaDetection, IsDetected) {
  74. EXPECT_EQ (true, (std::is_same< true_, is_detected<try_type, A<int>> >()));
  75. EXPECT_EQ (true, (std::is_same< false_, is_detected<try_none, A<int>> >()));
  76. EXPECT_EQ (true, (std::is_same< true_, is_detected<try_ctor1, A<int>> >()));
  77. EXPECT_EQ (true, (std::is_same< false_, is_detected<try_ctor2, A<int>> >()));
  78. EXPECT_EQ (true, (std::is_same< true_, is_detected<try_ppT, A<int>> >()));
  79. EXPECT_EQ (true, (std::is_same< false_, is_detected<try_Tpp, A<int>> >()));
  80. EXPECT_EQ (true, (std::is_same< true_, is_detected<try_sfun, A<int>> >()));
  81. EXPECT_EQ (true, (std::is_same< false_, is_detected<try_sfun, A<double>> >()));
  82. EXPECT_EQ (true, (std::is_same< true_, is_detected<mFun, int, void> >()));
  83. EXPECT_EQ (true, (std::is_same< false_, is_detected<mFun, char> >()));
  84. EXPECT_EQ (true, (std::is_same< false_, is_detected<mFun, char, void, void> >()));
  85. EXPECT_EQ (true, (is_detected_v<try_type, A<int>>));
  86. EXPECT_EQ (false,(is_detected_v<try_none, A<int>>));
  87. EXPECT_EQ (true, (is_detected_v<mFun, int, void>));
  88. }
  89. /*
  90. * Idiom
  91. */
  92. TEST(TmetaDetection, Toolkit) {
  93. // detected_t
  94. EXPECT_EQ (true, (std::is_same< int, detected_t<try_type, A<int>> >()));
  95. EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_none, A<int>> >()));
  96. EXPECT_EQ (true, (std::is_same< A<int>, detected_t< try_ctor1, A<int>> >()));
  97. EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_ctor2, A<int>> >()));
  98. EXPECT_EQ (true, (std::is_same< A<int>&,detected_t< try_ppT, A<int>> >()));
  99. EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_Tpp, A<int>> >()));
  100. EXPECT_EQ (true, (std::is_same< int, detected_t< try_sfun, A<int>> >()));
  101. EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_sfun, A<double>> >()));
  102. EXPECT_EQ (true, (std::is_same< nat_, detected_t<mFun, void> >()));
  103. EXPECT_EQ (true, (std::is_same< mFun<int, int>,
  104. detected_t<mFun, int, int> >()));
  105. // detected_or_t
  106. EXPECT_EQ (true, (std::is_same< int, detected_or_t<Foo, try_type, A<int>> >()));
  107. EXPECT_EQ (true, (std::is_same< Foo, detected_or_t<Foo, try_none, A<int>> >()));
  108. EXPECT_EQ (true, (std::is_same< A<int>, detected_or_t<void, try_ctor1, A<int>> >()));
  109. EXPECT_EQ (true, (std::is_same< void, detected_or_t<void, try_ctor2, A<int>> >()));
  110. EXPECT_EQ (true, (std::is_same< A<int>&,detected_or_t<nil_, try_ppT, A<int>> >()));
  111. EXPECT_EQ (true, (std::is_same< nil_, detected_or_t<nil_, try_Tpp, A<int>> >()));
  112. EXPECT_EQ (true, (std::is_same< int, detected_or_t<void*, try_sfun, A<int>> >()));
  113. EXPECT_EQ (true, (std::is_same< void*, detected_or_t<void*, try_sfun, A<double>> >()));
  114. EXPECT_EQ (true, (std::is_same< nil_, detected_or_t<nil_, mFun, int> >()));
  115. EXPECT_EQ (true, (std::is_same< mFun<char, int>,
  116. detected_or_t<void, mFun, char, int> >()));
  117. // is_detected_exact
  118. EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< int, try_type, A<int>> >()));
  119. EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< int, try_none, A<int>> >()));
  120. EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< A<int>, try_ctor1, A<int>> >()));
  121. EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< A<int>, try_ctor2, A<int>> >()));
  122. EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< A<int>&,try_ppT, A<int>> >()));
  123. EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< A<int>&,try_Tpp, A<int>> >()));
  124. EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< int, try_sfun, A<int>> >()));
  125. EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< int, try_sfun, A<double>> >()));
  126. EXPECT_EQ (true, (std::is_same<true_, is_detected_exact<mFun<char, int>, mFun, char, int> >()));
  127. EXPECT_EQ (true, (std::is_same<false_, is_detected_exact<mFun<int, int>, mFun, int> >())); // it would be better to check against mFun<int>
  128. EXPECT_EQ (true, (is_detected_exact_v< int, try_type, A<int>> ));
  129. EXPECT_EQ (false,(is_detected_exact_v< int, try_none, A<int>> ));
  130. // is_detected_convertible
  131. EXPECT_EQ (true, (std::is_same<true_, is_detected_convertible< int, try_type, A<char>> >()));
  132. EXPECT_EQ (true, (std::is_same<false_, is_detected_convertible< int, try_none, A<int>> >()));
  133. EXPECT_EQ (true, (std::is_same<false_, is_detected_convertible< mFun<int, int>, mFun, char, int> >()));
  134. EXPECT_EQ (true, (is_detected_convertible_v< int, try_type, A<char>> ));
  135. EXPECT_EQ (false,(is_detected_convertible_v< int, try_none, A<int>> ));
  136. }
  137. }