diff options
Diffstat (limited to 'src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp')
-rw-r--r-- | src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp | 105 |
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 00000000..4456aef3 --- /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] + +} + +} |