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