]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / hana / example / tutorial / quickstart.switchAny.cpp
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4
5 // Make sure `assert` always triggers an assertion
6 #ifdef NDEBUG
7 # undef NDEBUG
8 #endif
9
10 //! [full]
11 #include <boost/hana.hpp>
12
13 #include <boost/any.hpp>
14 #include <cassert>
15 #include <string>
16 #include <typeindex>
17 #include <typeinfo>
18 #include <utility>
19 namespace hana = boost::hana;
20
21 //! [cases]
22 template <typename T>
23 auto case_ = [](auto f) {
24 return hana::make_pair(hana::type_c<T>, f);
25 };
26
27 struct default_t;
28 auto default_ = case_<default_t>;
29 //! [cases]
30
31 //! [process]
32 template <typename Any, typename Default>
33 auto process(Any&, std::type_index const&, Default& default_) {
34 return default_();
35 }
36
37 template <typename Any, typename Default, typename Case, typename ...Rest>
38 auto process(Any& a, std::type_index const& t, Default& default_,
39 Case& case_, Rest& ...rest)
40 {
41 using T = typename decltype(+hana::first(case_))::type;
42 return t == typeid(T) ? hana::second(case_)(*boost::unsafe_any_cast<T>(&a))
43 : process(a, t, default_, rest...);
44 }
45 //! [process]
46
47 //! [switch_]
48 template <typename Any>
49 auto switch_(Any& a) {
50 return [&a](auto ...cases_) {
51 auto cases = hana::make_tuple(cases_...);
52
53 auto default_ = hana::find_if(cases, [](auto const& c) {
54 return hana::first(c) == hana::type_c<default_t>;
55 });
56 static_assert(default_ != hana::nothing,
57 "switch is missing a default_ case");
58
59 auto rest = hana::filter(cases, [](auto const& c) {
60 return hana::first(c) != hana::type_c<default_t>;
61 });
62
63 return hana::unpack(rest, [&](auto& ...rest) {
64 return process(a, a.type(), hana::second(*default_), rest...);
65 });
66 };
67 }
68 //! [switch_]
69 //! [full]
70
71
72 int main() {
73 using namespace std::literals;
74
75 {
76
77 //! [usage]
78 boost::any a = 'x';
79 std::string r = switch_(a)(
80 case_<int>([](auto i) { return "int: "s + std::to_string(i); }),
81 case_<char>([](auto c) { return "char: "s + std::string{c}; }),
82 default_([] { return "unknown"s; })
83 );
84
85 assert(r == "char: x"s);
86 //! [usage]
87
88 }{
89
90 //! [result_inference]
91 boost::any a = 'x';
92 auto r = switch_(a)(
93 case_<int>([](auto) -> int { return 1; }),
94 case_<char>([](auto) -> long { return 2l; }),
95 default_([]() -> long long { return 3ll; })
96 );
97
98 // r is inferred to be a long long
99 static_assert(std::is_same<decltype(r), long long>{}, "");
100 assert(r == 2ll);
101 //! [result_inference]
102
103 }
104
105 }