Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. 2018 All Rights Reserved.
3 : * http://soramitsu.co.jp
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #ifndef IROHA_VISITOR_HPP
19 : #define IROHA_VISITOR_HPP
20 :
21 : #include <boost/variant/apply_visitor.hpp> // for boost::apply_visitor
22 : #include <type_traits> // for std::decay
23 : #include <utility> // for std::forward
24 :
25 : namespace iroha {
26 :
27 : template <typename... Lambdas>
28 : struct lambda_visitor;
29 :
30 : template <typename Lambda, typename... Lambdas>
31 : struct lambda_visitor<Lambda, Lambdas...>
32 : : public Lambda, public lambda_visitor<Lambdas...> {
33 : using Lambda::operator();
34 : using lambda_visitor<Lambdas...>::operator();
35 :
36 : lambda_visitor(Lambda lambda, Lambdas... lambdas)
37 35398 : : Lambda(lambda), lambda_visitor<Lambdas...>(lambdas...) {}
38 : };
39 :
40 : template <typename Lambda>
41 : struct lambda_visitor<Lambda> : public Lambda {
42 : using Lambda::operator();
43 :
44 : lambda_visitor(Lambda lambda) : Lambda(lambda) {}
45 : };
46 :
47 : /**
48 : * @brief Convenient in-place compile-time visitor creation, from a set of
49 : * lambdas
50 : *
51 : * @code
52 : * make_visitor([](int a){ return 1; },
53 : * [](std::string b) { return 2; });
54 : * @nocode
55 : *
56 : * is essentially the same as
57 : *
58 : * @code
59 : * struct visitor : public boost::static_visitor<int> {
60 : * int operator()(int a) { return 1; }
61 : * int operator()(std::string b) { return 2; }
62 : * }
63 : * @nocode
64 : *
65 : * @param lambdas
66 : * @return visitor
67 : */
68 : template <class... Fs>
69 : constexpr auto make_visitor(Fs &&... fs) {
70 : using visitor_type = lambda_visitor<std::decay_t<Fs>...>;
71 36113 : return visitor_type(std::forward<Fs>(fs)...);
72 0 : }
73 :
74 : /**
75 : * @brief Inplace visitor for boost::variant.
76 : * @code
77 : * boost::variant<int, std::string> value = "1234";
78 : * ...
79 : * visit_in_place(value,
80 : * [](int v) { std::cout << "(int)" << v; },
81 : * [](std::string v) { std::cout << "(string)" << v;}
82 : * );
83 : * @nocode
84 : *
85 : * @param variant
86 : * @param lambdas
87 : * @param lambdas
88 : */
89 : template <typename TVariant, typename... TVisitors>
90 : constexpr decltype(auto) visit_in_place(TVariant &&variant,
91 : TVisitors &&... visitors) {
92 36112 : return boost::apply_visitor(
93 36112 : make_visitor(std::forward<TVisitors>(visitors)...),
94 36112 : std::forward<TVariant>(variant));
95 0 : }
96 :
97 : /// apply Matcher to optional T
98 : template <typename T, typename Matcher>
99 : constexpr decltype(auto) match(T &&t, Matcher &&m) {
100 : return std::forward<T>(t) ? std::forward<Matcher>(m)(*std::forward<T>(t))
101 : : std::forward<Matcher>(m)();
102 : }
103 :
104 : /// construct visitor from Fs and apply it to optional T
105 : template <typename T, typename... Fs>
106 : constexpr decltype(auto) match_in_place(T &&t, Fs &&... fs) {
107 : return match(std::forward<T>(t), make_visitor(std::forward<Fs>(fs)...));
108 : }
109 : } // namespace iroha
110 :
111 : #endif // IROHA_VISITOR_HPP
|