summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/example/tutorial/introspection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/hana/example/tutorial/introspection.cpp')
-rw-r--r--src/boost/libs/hana/example/tutorial/introspection.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/boost/libs/hana/example/tutorial/introspection.cpp b/src/boost/libs/hana/example/tutorial/introspection.cpp
new file mode 100644
index 000000000..3b72db447
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introspection.cpp
@@ -0,0 +1,158 @@
+// 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]
+}