summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp')
-rw-r--r--src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp b/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
new file mode 100644
index 000000000..4456aef32
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
@@ -0,0 +1,105 @@
+// 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)
+
+// Make sure `assert` always triggers an assertion
+#ifdef NDEBUG
+# undef NDEBUG
+#endif
+
+//! [full]
+#include <boost/hana.hpp>
+
+#include <boost/any.hpp>
+#include <cassert>
+#include <string>
+#include <typeindex>
+#include <typeinfo>
+#include <utility>
+namespace hana = boost::hana;
+
+//! [cases]
+template <typename T>
+auto case_ = [](auto f) {
+ return hana::make_pair(hana::type_c<T>, f);
+};
+
+struct default_t;
+auto default_ = case_<default_t>;
+//! [cases]
+
+//! [process]
+template <typename Any, typename Default>
+auto process(Any&, std::type_index const&, Default& default_) {
+ return default_();
+}
+
+template <typename Any, typename Default, typename Case, typename ...Rest>
+auto process(Any& a, std::type_index const& t, Default& default_,
+ Case& case_, Rest& ...rest)
+{
+ using T = typename decltype(+hana::first(case_))::type;
+ return t == typeid(T) ? hana::second(case_)(*boost::unsafe_any_cast<T>(&a))
+ : process(a, t, default_, rest...);
+}
+//! [process]
+
+//! [switch_]
+template <typename Any>
+auto switch_(Any& a) {
+ return [&a](auto ...cases_) {
+ auto cases = hana::make_tuple(cases_...);
+
+ auto default_ = hana::find_if(cases, [](auto const& c) {
+ return hana::first(c) == hana::type_c<default_t>;
+ });
+ static_assert(default_ != hana::nothing,
+ "switch is missing a default_ case");
+
+ auto rest = hana::filter(cases, [](auto const& c) {
+ return hana::first(c) != hana::type_c<default_t>;
+ });
+
+ return hana::unpack(rest, [&](auto& ...rest) {
+ return process(a, a.type(), hana::second(*default_), rest...);
+ });
+ };
+}
+//! [switch_]
+//! [full]
+
+
+int main() {
+using namespace std::literals;
+
+{
+
+//! [usage]
+boost::any a = 'x';
+std::string r = switch_(a)(
+ case_<int>([](auto i) { return "int: "s + std::to_string(i); }),
+ case_<char>([](auto c) { return "char: "s + std::string{c}; }),
+ default_([] { return "unknown"s; })
+);
+
+assert(r == "char: x"s);
+//! [usage]
+
+}{
+
+//! [result_inference]
+boost::any a = 'x';
+auto r = switch_(a)(
+ case_<int>([](auto) -> int { return 1; }),
+ case_<char>([](auto) -> long { return 2l; }),
+ default_([]() -> long long { return 3ll; })
+);
+
+// r is inferred to be a long long
+static_assert(std::is_same<decltype(r), long long>{}, "");
+assert(r == 2ll);
+//! [result_inference]
+
+}
+
+}