123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- // Copyright Louis Dionne 2013-2017
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- #include <boost/hana/assert.hpp>
- #include <boost/hana/equal.hpp>
- #include <boost/hana/not.hpp>
- #include <boost/hana/traits.hpp>
- #include <boost/hana/type.hpp>
- #include <support/tracked.hpp>
- #include <type_traits>
- namespace hana = boost::hana;
- struct undefined { };
- struct static_nested_member { static const int member = 1; };
- struct static_nested_member_array { static int member[3]; };
- struct nested_template_struct { template <typename ...> struct nested; };
- struct nested_template_alias { template <typename ...> using nested = void; };
- int main() {
- // Check for a non-static member
- {
- struct yes { int member; };
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(
- hana::traits::declval(t).member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(
- t.member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- // Check for a non-static member function
- {
- struct yes { int member() const; };
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(
- hana::traits::declval(t).member()
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(
- t.member()
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- // Check for a static member
- {
- using yes = static_nested_member;
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(
- decltype(t)::type::member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(
- std::remove_reference_t<decltype(t)>::member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- // Check for a nested type
- {
- struct yes { using nested = void; };
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(hana::type_c<
- typename decltype(t)::type::nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::type_c<
- typename std::remove_reference_t<decltype(t)>::nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- // Check for a nested template
- {
- { // template struct
- using yes = nested_template_struct;
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(hana::template_<
- decltype(t)::type::template nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::template_<
- std::remove_reference_t<decltype(t)>::template nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- { // template alias
- using yes = nested_template_alias;
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(hana::template_<
- decltype(t)::type::template nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(hana::template_<
- std::remove_reference_t<decltype(t)>::template nested
- >) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- }
- // Make sure that checking for a nested static or non-static member
- // works even when the type of that member is an array type or
- // something that can't be returned from a function.
- {
- { // non-static member
- struct yes { int member[3]; };
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(
- (void)hana::traits::declval(t).member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(
- (void)t.member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- { // static member
- using yes = static_nested_member_array;
- struct no { };
- auto from_type = hana::is_valid([](auto t) -> decltype(
- (void)decltype(t)::type::member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_type(hana::type_c<yes>));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_type(hana::type_c<no>)));
- auto from_object = hana::is_valid([](auto&& t) -> decltype(
- (void)std::remove_reference_t<decltype(t)>::member
- ) { });
- BOOST_HANA_CONSTANT_CHECK(from_object(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(from_object(no{})));
- }
- }
- // Make sure the result of a `is_valid` function is constexpr
- // even when called on non-constexpr arguments.
- {
- int i;
- auto f = hana::is_valid([](auto) { });
- constexpr auto result = f(i);
- (void)result;
- }
- // Make sure `is_valid` works with non-PODs.
- {
- hana::is_valid(undefined{})(Tracked{1});
- hana::is_valid([t = Tracked{1}](auto) { return 1; })(Tracked{1});
- }
- // Check `is_valid` with a nullary function.
- {
- auto f = [](auto ...x) { (void)sizeof...(x); /* -Wunused-param */ };
- auto g = [](auto ...x) -> char(*)[sizeof...(x)] { };
- BOOST_HANA_CONSTANT_CHECK(hana::is_valid(f)());
- BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_valid(g)()));
- }
- // Call `is_valid` in the non-curried form.
- {
- struct yes { int member; };
- struct no { };
- auto f = [](auto&& t) -> decltype(t.member) { };
- BOOST_HANA_CONSTANT_CHECK(hana::is_valid(f, yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_valid(f, no{})));
- }
- }
|