]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/util/variant_utils.hh
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / include / seastar / util / variant_utils.hh
1 /*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
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,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18 /*
19 * Copyright (C) 2017 ScyllaDB.
20 */
21
22 #pragma once
23
24 #include <seastar/util/std-compat.hh>
25 #include <boost/version.hpp>
26
27 #if (BOOST_VERSION < 105800)
28
29 #error "Boost version >= 1.58 is required for using variant visitation helpers."
30 #error "Earlier versions lack support for return value deduction and move-only return values"
31
32 #endif
33
34 namespace seastar {
35
36 /// \cond internal
37 namespace internal {
38
39 #if __cplusplus >= 201703L // C++17
40
41 template<typename... Args>
42 struct variant_visitor : Args... {
43 variant_visitor(Args&&... a) : Args(std::move(a))... {}
44 using Args::operator()...;
45 };
46
47 template<typename... Args> variant_visitor(Args&&...) -> variant_visitor<Args...>;
48
49 #else
50
51 template <typename... Args>
52 struct variant_visitor;
53
54 template <typename FuncObj, typename... Args>
55 struct variant_visitor<FuncObj, Args...> : FuncObj, variant_visitor<Args...>
56 {
57 variant_visitor(FuncObj&& func_obj, Args&&... args)
58 : FuncObj(std::move(func_obj))
59 , variant_visitor<Args...>(std::move(args)...) {}
60
61 using FuncObj::operator();
62 using variant_visitor<Args...>::operator();
63 };
64
65 template <typename FuncObj>
66 struct variant_visitor<FuncObj> : FuncObj
67 {
68 variant_visitor(FuncObj&& func_obj) : FuncObj(std::forward<FuncObj>(func_obj)) {}
69
70 using FuncObj::operator();
71 };
72
73 #endif
74
75 }
76 /// \endcond
77
78 /// \addtogroup utilities
79 /// @{
80
81 /// Creates a visitor from function objects.
82 ///
83 /// Returns a visitor object comprised of the provided function objects. Can be
84 /// used with std::variant, boost::variant or any other custom variant
85 /// implementation.
86 ///
87 /// \param args function objects each accepting one or some types stored in the variant as input
88 template <typename... Args>
89 auto make_visitor(Args&&... args)
90 {
91 return internal::variant_visitor<Args...>(std::forward<Args>(args)...);
92 }
93
94 /// Applies a static visitor comprised of supplied lambdas to a variant.
95 /// Note that the lambdas should cover all the types that the variant can possibly hold.
96 ///
97 /// Returns the common type of return types of all lambdas.
98 ///
99 /// \tparam Variant the type of a variant
100 /// \tparam Args types of lambda objects
101 /// \param variant the variant object
102 /// \param args lambda objects each accepting one or some types stored in the variant as input
103 /// \return
104 template <typename Variant, typename... Args>
105 inline auto visit(Variant&& variant, Args&&... args)
106 {
107 static_assert(sizeof...(Args) > 0, "At least one lambda must be provided for visitation");
108 #ifdef SEASTAR_USE_STD_OPTIONAL_VARIANT_STRINGVIEW
109 return std::visit(
110 #else
111 return boost::apply_visitor(
112 #endif
113 make_visitor(std::forward<Args>(args)...),
114 variant);
115 }
116
117 #ifdef SEASTAR_USE_STD_OPTIONAL_VARIANT_STRINGVIEW
118
119 namespace internal {
120 template<typename... Args>
121 struct castable_variant {
122 compat::variant<Args...> var;
123
124 template<typename... SuperArgs>
125 operator compat::variant<SuperArgs...>() && {
126 return std::visit([] (auto&& x) {
127 return std::variant<SuperArgs...>(std::move(x));
128 }, var);
129 }
130 };
131 }
132
133 template<typename... Args>
134 internal::castable_variant<Args...> variant_cast(compat::variant<Args...>&& var) {
135 return {std::move(var)};
136 }
137
138 template<typename... Args>
139 internal::castable_variant<Args...> variant_cast(const compat::variant<Args...>& var) {
140 return {var};
141 }
142
143 #else
144
145 template<typename Variant>
146 Variant variant_cast(Variant&& var) {
147 return std::forward<Variant>(var);
148 }
149
150 #endif
151
152 /// @}
153
154 }