is_valid.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #include <boost/hana/assert.hpp>
  5. #include <boost/hana/equal.hpp>
  6. #include <boost/hana/not.hpp>
  7. #include <boost/hana/traits.hpp>
  8. #include <boost/hana/type.hpp>
  9. #include <support/tracked.hpp>
  10. #include <type_traits>
  11. namespace hana = boost::hana;
  12. struct undefined { };
  13. struct static_nested_member { static const int member = 1; };
  14. struct static_nested_member_array { static int member[3]; };
  15. struct nested_template_struct { template <typename ...> struct nested; };
  16. struct nested_template_alias { template <typename ...> using nested = void; };
  17. int main() {
  18. // Check for a non-static member
  19. {
  20. struct yes { int member; };
  21. struct no { };
  22. auto from_type = hana::is_valid([](auto t) -> decltype(
  23. hana::traits::declval(t).member
  24. ) { });
  25. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  26. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  27. auto from_object = hana::is_valid([](auto&& t) -> decltype(
  28. t.member
  29. ) { });
  30. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  31. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  32. }
  33. // Check for a non-static member function
  34. {
  35. struct yes { int member() const; };
  36. struct no { };
  37. auto from_type = hana::is_valid([](auto t) -> decltype(
  38. hana::traits::declval(t).member()
  39. ) { });
  40. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  41. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  42. auto from_object = hana::is_valid([](auto&& t) -> decltype(
  43. t.member()
  44. ) { });
  45. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  46. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  47. }
  48. // Check for a static member
  49. {
  50. using yes = static_nested_member;
  51. struct no { };
  52. auto from_type = hana::is_valid([](auto t) -> decltype(
  53. decltype(t)::type::member
  54. ) { });
  55. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  56. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  57. auto from_object = hana::is_valid([](auto&& t) -> decltype(
  58. std::remove_reference_t<decltype(t)>::member
  59. ) { });
  60. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  61. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  62. }
  63. // Check for a nested type
  64. {
  65. struct yes { using nested = void; };
  66. struct no { };
  67. auto from_type = hana::is_valid([](auto t) -> decltype(hana::type_c<
  68. typename decltype(t)::type::nested
  69. >) { });
  70. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  71. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  72. auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::type_c<
  73. typename std::remove_reference_t<decltype(t)>::nested
  74. >) { });
  75. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  76. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  77. }
  78. // Check for a nested template
  79. {
  80. { // template struct
  81. using yes = nested_template_struct;
  82. struct no { };
  83. auto from_type = hana::is_valid([](auto t) -> decltype(hana::template_<
  84. decltype(t)::type::template nested
  85. >) { });
  86. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  87. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  88. auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::template_<
  89. std::remove_reference_t<decltype(t)>::template nested
  90. >) { });
  91. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  92. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  93. }
  94. { // template alias
  95. using yes = nested_template_alias;
  96. struct no { };
  97. auto from_type = hana::is_valid([](auto t) -> decltype(hana::template_<
  98. decltype(t)::type::template nested
  99. >) { });
  100. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  101. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  102. auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::template_<
  103. std::remove_reference_t<decltype(t)>::template nested
  104. >) { });
  105. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  106. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  107. }
  108. }
  109. // Make sure that checking for a nested static or non-static member
  110. // works even when the type of that member is an array type or
  111. // something that can't be returned from a function.
  112. {
  113. { // non-static member
  114. struct yes { int member[3]; };
  115. struct no { };
  116. auto from_type = hana::is_valid([](auto t) -> decltype(
  117. (void)hana::traits::declval(t).member
  118. ) { });
  119. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  120. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  121. auto from_object = hana::is_valid([](auto&& t) -> decltype(
  122. (void)t.member
  123. ) { });
  124. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  125. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  126. }
  127. { // static member
  128. using yes = static_nested_member_array;
  129. struct no { };
  130. auto from_type = hana::is_valid([](auto t) -> decltype(
  131. (void)decltype(t)::type::member
  132. ) { });
  133. BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
  134. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
  135. auto from_object = hana::is_valid([](auto&& t) -> decltype(
  136. (void)std::remove_reference_t<decltype(t)>::member
  137. ) { });
  138. BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
  139. BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
  140. }
  141. }
  142. // Make sure the result of a `is_valid` function is constexpr
  143. // even when called on non-constexpr arguments.
  144. {
  145. int i;
  146. auto f = hana::is_valid([](auto) { });
  147. constexpr auto result = f(i);
  148. (void)result;
  149. }
  150. // Make sure `is_valid` works with non-PODs.
  151. {
  152. hana::is_valid(undefined{})(Tracked{1});
  153. hana::is_valid([t = Tracked{1}](auto) { return 1; })(Tracked{1});
  154. }
  155. // Check `is_valid` with a nullary function.
  156. {
  157. auto f = [](auto ...x) { (void)sizeof...(x); /* -Wunused-param */ };
  158. auto g = [](auto ...x) -> char(*)[sizeof...(x)] { };
  159. BOOST_HANA_CONSTANT_CHECK(hana::is_valid(f)());
  160. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_valid(g)()));
  161. }
  162. // Call `is_valid` in the non-curried form.
  163. {
  164. struct yes { int member; };
  165. struct no { };
  166. auto f = [](auto&& t) -> decltype(t.member) { };
  167. BOOST_HANA_CONSTANT_CHECK(hana::is_valid(f, yes{}));
  168. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_valid(f, no{})));
  169. }
  170. }