Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_VISITOR_HPP
7 : #define IROHA_VISITOR_HPP
8 :
9 : #include <boost/variant/apply_visitor.hpp> // for boost::apply_visitor
10 : #include <type_traits> // for std::decay
11 : #include <utility> // for std::forward
12 :
13 : namespace iroha {
14 :
15 : template <typename... Lambdas>
16 : struct lambda_visitor;
17 :
18 : template <typename Lambda, typename... Lambdas>
19 : struct lambda_visitor<Lambda, Lambdas...>
20 : : public Lambda, public lambda_visitor<Lambdas...> {
21 : using Lambda::operator();
22 : using lambda_visitor<Lambdas...>::operator();
23 :
24 : lambda_visitor(Lambda lambda, Lambdas... lambdas)
25 83970 : : Lambda(lambda), lambda_visitor<Lambdas...>(lambdas...) {}
26 : };
27 :
28 : template <typename Lambda>
29 : struct lambda_visitor<Lambda> : public Lambda {
30 : using Lambda::operator();
31 :
32 : lambda_visitor(Lambda lambda) : Lambda(lambda) {}
33 : };
34 :
35 : /**
36 : * @brief Convenient in-place compile-time visitor creation, from a set of
37 : * lambdas
38 : *
39 : * @code
40 : * make_visitor([](int a){ return 1; },
41 : * [](std::string b) { return 2; });
42 : * @nocode
43 : *
44 : * is essentially the same as
45 : *
46 : * @code
47 : * struct visitor : public boost::static_visitor<int> {
48 : * int operator()(int a) { return 1; }
49 : * int operator()(std::string b) { return 2; }
50 : * }
51 : * @nocode
52 : *
53 : * @param lambdas
54 : * @return visitor
55 : */
56 : template <class... Fs>
57 : constexpr auto make_visitor(Fs &&... fs) {
58 : using visitor_type = lambda_visitor<std::decay_t<Fs>...>;
59 87040 : return visitor_type(std::forward<Fs>(fs)...);
60 0 : }
61 :
62 : /**
63 : * @brief Inplace visitor for boost::variant.
64 : * @code
65 : * boost::variant<int, std::string> value = "1234";
66 : * ...
67 : * visit_in_place(value,
68 : * [](int v) { std::cout << "(int)" << v; },
69 : * [](std::string v) { std::cout << "(string)" << v;}
70 : * );
71 : * @nocode
72 : *
73 : * @param variant
74 : * @param lambdas
75 : * @param lambdas
76 : */
77 : template <typename TVariant, typename... TVisitors>
78 : constexpr decltype(auto) visit_in_place(TVariant &&variant,
79 : TVisitors &&... visitors) {
80 87131 : return boost::apply_visitor(
81 87131 : make_visitor(std::forward<TVisitors>(visitors)...),
82 87131 : std::forward<TVariant>(variant));
83 0 : }
84 :
85 : /// apply Matcher to optional T
86 : template <typename T, typename Matcher>
87 : constexpr decltype(auto) match(T &&t, Matcher &&m) {
88 : return std::forward<T>(t) ? std::forward<Matcher>(m)(*std::forward<T>(t))
89 : : std::forward<Matcher>(m)();
90 : }
91 :
92 : /// construct visitor from Fs and apply it to optional T
93 : template <typename T, typename... Fs>
94 : constexpr decltype(auto) match_in_place(T &&t, Fs &&... fs) {
95 : return match(std::forward<T>(t), make_visitor(std::forward<Fs>(fs)...));
96 : }
97 : } // namespace iroha
98 :
99 : #endif // IROHA_VISITOR_HPP
|