123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- // 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.hpp>
- #include <string>
- #include <type_traits>
- #include <utility>
- namespace hana = boost::hana;
- struct yes { std::string toString() const { return "yes"; } };
- struct no { };
- namespace has_toString_then {
- //! [has_toString.then]
- template <typename T, typename = void>
- struct has_toString
- : std::false_type
- { };
- template <typename T>
- struct has_toString<T, decltype((void)std::declval<T>().toString())>
- : std::true_type
- { };
- //! [has_toString.then]
- static_assert(has_toString<yes>::value, "");
- static_assert(!has_toString<no>::value, "");
- }
- //! [has_toString.now]
- auto has_toString = hana::is_valid([](auto&& obj) -> decltype(obj.toString()) { });
- //! [has_toString.now]
- BOOST_HANA_CONSTANT_CHECK(has_toString(yes{}));
- BOOST_HANA_CONSTANT_CHECK(hana::not_(has_toString(no{})));
- namespace optionalToString_then {
- //! [optionalToString.then]
- template <typename T>
- auto optionalToString(T const& obj)
- -> std::enable_if_t<decltype(has_toString(obj))::value, std::string>
- { return obj.toString(); }
- template <typename T>
- auto optionalToString(T const& obj)
- -> std::enable_if_t<decltype(!has_toString(obj))::value, std::string>
- { return "toString not defined"; }
- //! [optionalToString.then]
- // make sure they compile
- template std::string optionalToString(yes const&);
- template std::string optionalToString(no const&);
- }
- //! [optionalToString]
- template <typename T>
- std::string optionalToString(T const& obj) {
- return hana::if_(has_toString(obj),
- [](auto& x) { return x.toString(); },
- [](auto& x) { return "toString not defined"; }
- )(obj);
- }
- //! [optionalToString]
- int main() {
- BOOST_HANA_RUNTIME_CHECK(optionalToString(yes{}) == "yes");
- BOOST_HANA_RUNTIME_CHECK(optionalToString(no{}) == "toString not defined");
- {
- //! [non_static_member_from_object]
- auto has_member = hana::is_valid([](auto&& x) -> decltype((void)x.member) { });
- struct Foo { int member[4]; };
- struct Bar { };
- BOOST_HANA_CONSTANT_CHECK(has_member(Foo{}));
- BOOST_HANA_CONSTANT_CHECK(!has_member(Bar{}));
- //! [non_static_member_from_object]
- }{
- //! [non_static_member_from_type]
- auto has_member = hana::is_valid([](auto t) -> decltype(
- (void)hana::traits::declval(t).member
- ) { });
- struct Foo { int member[4]; };
- struct Bar { };
- BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
- BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
- //! [non_static_member_from_type]
- }{
- //! [nested_type_name]
- auto has_member = hana::is_valid([](auto t) -> hana::type<
- typename decltype(t)::type::member
- //^^^^^^^^ needed because of the dependent context
- > { });
- struct Foo { struct member; /* not defined! */ };
- struct Bar { };
- BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
- BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
- //! [nested_type_name]
- }
- }
- namespace static_member {
- //! [static_member]
- auto has_member = hana::is_valid([](auto t) -> decltype(
- (void)decltype(t)::type::member
- ) { });
- struct Foo { static int member[4]; };
- struct Bar { };
- BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
- BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
- //! [static_member]
- }
- namespace nested_template {
- //! [nested_template]
- auto has_member = hana::is_valid([](auto t) -> decltype(hana::template_<
- decltype(t)::type::template member
- // ^^^^^^^^ needed because of the dependent context
- >) { });
- struct Foo { template <typename ...> struct member; };
- struct Bar { };
- BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
- BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
- //! [nested_template]
- }
- namespace template_specialization {
- //! [template_specialization]
- template <typename T, typename U>
- struct Foo;
- template <typename T>
- struct Bar;
- auto is_binary_template = hana::is_valid([](auto trait) -> decltype(
- trait(hana::type_c<void>, hana::type_c<void>)
- ) { });
- BOOST_HANA_CONSTANT_CHECK(is_binary_template(hana::template_<Foo>));
- BOOST_HANA_CONSTANT_CHECK(!is_binary_template(hana::template_<Bar>));
- //! [template_specialization]
- }
|