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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * Copyright (C) 2017 ScyllaDB.
24 #include <seastar/util/std-compat.hh>
25 #include <boost/version.hpp>
27 #if (BOOST_VERSION < 105800)
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"
39 #if __cplusplus >= 201703L // C++17
41 template<typename... Args>
42 struct variant_visitor : Args... {
43 variant_visitor(Args&&... a) : Args(std::move(a))... {}
44 using Args::operator()...;
47 template<typename... Args> variant_visitor(Args&&...) -> variant_visitor<Args...>;
51 template <typename... Args>
52 struct variant_visitor;
54 template <typename FuncObj, typename... Args>
55 struct variant_visitor<FuncObj, Args...> : FuncObj, variant_visitor<Args...>
57 variant_visitor(FuncObj&& func_obj, Args&&... args)
58 : FuncObj(std::move(func_obj))
59 , variant_visitor<Args...>(std::move(args)...) {}
61 using FuncObj::operator();
62 using variant_visitor<Args...>::operator();
65 template <typename FuncObj>
66 struct variant_visitor<FuncObj> : FuncObj
68 variant_visitor(FuncObj&& func_obj) : FuncObj(std::forward<FuncObj>(func_obj)) {}
70 using FuncObj::operator();
78 /// \addtogroup utilities
81 /// Creates a visitor from function objects.
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
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)
91 return internal::variant_visitor<Args...>(std::forward<Args>(args)...);
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.
97 /// Returns the common type of return types of all lambdas.
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
104 template <typename Variant, typename... Args>
105 inline auto visit(Variant&& variant, Args&&... args)
107 static_assert(sizeof...(Args) > 0, "At least one lambda must be provided for visitation");
108 #ifdef SEASTAR_USE_STD_OPTIONAL_VARIANT_STRINGVIEW
111 return boost::apply_visitor(
113 make_visitor(std::forward<Args>(args)...),
117 #ifdef SEASTAR_USE_STD_OPTIONAL_VARIANT_STRINGVIEW
120 template<typename... Args>
121 struct castable_variant {
122 compat::variant<Args...> var;
124 template<typename... SuperArgs>
125 operator compat::variant<SuperArgs...>() && {
126 return std::visit([] (auto&& x) {
127 return std::variant<SuperArgs...>(std::move(x));
133 template<typename... Args>
134 internal::castable_variant<Args...> variant_cast(compat::variant<Args...>&& var) {
135 return {std::move(var)};
138 template<typename... Args>
139 internal::castable_variant<Args...> variant_cast(const compat::variant<Args...>& var) {
145 template<typename Variant>
146 Variant variant_cast(Variant&& var) {
147 return std::forward<Variant>(var);