introspection.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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.hpp>
  5. #include <string>
  6. #include <type_traits>
  7. #include <utility>
  8. namespace hana = boost::hana;
  9. struct yes { std::string toString() const { return "yes"; } };
  10. struct no { };
  11. namespace has_toString_then {
  12. //! [has_toString.then]
  13. template <typename T, typename = void>
  14. struct has_toString
  15. : std::false_type
  16. { };
  17. template <typename T>
  18. struct has_toString<T, decltype((void)std::declval<T>().toString())>
  19. : std::true_type
  20. { };
  21. //! [has_toString.then]
  22. static_assert(has_toString<yes>::value, "");
  23. static_assert(!has_toString<no>::value, "");
  24. }
  25. //! [has_toString.now]
  26. auto has_toString = hana::is_valid([](auto&& obj) -> decltype(obj.toString()) { });
  27. //! [has_toString.now]
  28. BOOST_HANA_CONSTANT_CHECK(has_toString(yes{}));
  29. BOOST_HANA_CONSTANT_CHECK(hana::not_(has_toString(no{})));
  30. namespace optionalToString_then {
  31. //! [optionalToString.then]
  32. template <typename T>
  33. auto optionalToString(T const& obj)
  34. -> std::enable_if_t<decltype(has_toString(obj))::value, std::string>
  35. { return obj.toString(); }
  36. template <typename T>
  37. auto optionalToString(T const& obj)
  38. -> std::enable_if_t<decltype(!has_toString(obj))::value, std::string>
  39. { return "toString not defined"; }
  40. //! [optionalToString.then]
  41. // make sure they compile
  42. template std::string optionalToString(yes const&);
  43. template std::string optionalToString(no const&);
  44. }
  45. //! [optionalToString]
  46. template <typename T>
  47. std::string optionalToString(T const& obj) {
  48. return hana::if_(has_toString(obj),
  49. [](auto& x) { return x.toString(); },
  50. [](auto& x) { return "toString not defined"; }
  51. )(obj);
  52. }
  53. //! [optionalToString]
  54. int main() {
  55. BOOST_HANA_RUNTIME_CHECK(optionalToString(yes{}) == "yes");
  56. BOOST_HANA_RUNTIME_CHECK(optionalToString(no{}) == "toString not defined");
  57. {
  58. //! [non_static_member_from_object]
  59. auto has_member = hana::is_valid([](auto&& x) -> decltype((void)x.member) { });
  60. struct Foo { int member[4]; };
  61. struct Bar { };
  62. BOOST_HANA_CONSTANT_CHECK(has_member(Foo{}));
  63. BOOST_HANA_CONSTANT_CHECK(!has_member(Bar{}));
  64. //! [non_static_member_from_object]
  65. }{
  66. //! [non_static_member_from_type]
  67. auto has_member = hana::is_valid([](auto t) -> decltype(
  68. (void)hana::traits::declval(t).member
  69. ) { });
  70. struct Foo { int member[4]; };
  71. struct Bar { };
  72. BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
  73. BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
  74. //! [non_static_member_from_type]
  75. }{
  76. //! [nested_type_name]
  77. auto has_member = hana::is_valid([](auto t) -> hana::type<
  78. typename decltype(t)::type::member
  79. //^^^^^^^^ needed because of the dependent context
  80. > { });
  81. struct Foo { struct member; /* not defined! */ };
  82. struct Bar { };
  83. BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
  84. BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
  85. //! [nested_type_name]
  86. }
  87. }
  88. namespace static_member {
  89. //! [static_member]
  90. auto has_member = hana::is_valid([](auto t) -> decltype(
  91. (void)decltype(t)::type::member
  92. ) { });
  93. struct Foo { static int member[4]; };
  94. struct Bar { };
  95. BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
  96. BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
  97. //! [static_member]
  98. }
  99. namespace nested_template {
  100. //! [nested_template]
  101. auto has_member = hana::is_valid([](auto t) -> decltype(hana::template_<
  102. decltype(t)::type::template member
  103. // ^^^^^^^^ needed because of the dependent context
  104. >) { });
  105. struct Foo { template <typename ...> struct member; };
  106. struct Bar { };
  107. BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
  108. BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
  109. //! [nested_template]
  110. }
  111. namespace template_specialization {
  112. //! [template_specialization]
  113. template <typename T, typename U>
  114. struct Foo;
  115. template <typename T>
  116. struct Bar;
  117. auto is_binary_template = hana::is_valid([](auto trait) -> decltype(
  118. trait(hana::type_c<void>, hana::type_c<void>)
  119. ) { });
  120. BOOST_HANA_CONSTANT_CHECK(is_binary_template(hana::template_<Foo>));
  121. BOOST_HANA_CONSTANT_CHECK(!is_binary_template(hana::template_<Bar>));
  122. //! [template_specialization]
  123. }