]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/util/tuple_utils.hh
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / include / seastar / util / tuple_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 <tuple>
25 #include <utility>
26
27 namespace seastar {
28
29 /// \cond internal
30 namespace internal {
31
32 template<typename Tuple>
33 Tuple untuple(Tuple t) {
34 return t;
35 }
36
37 template<typename T>
38 T untuple(std::tuple<T> t) {
39 return std::get<0>(std::move(t));
40 }
41
42 template<typename Tuple, typename Function, size_t... I>
43 void tuple_for_each_helper(Tuple&& t, Function&& f, std::index_sequence<I...>&&) {
44 auto ignore_me = { (f(std::get<I>(std::forward<Tuple>(t))), 1)... };
45 (void)ignore_me;
46 }
47
48 template<typename Tuple, typename MapFunction, size_t... I>
49 auto tuple_map_helper(Tuple&& t, MapFunction&& f, std::index_sequence<I...>&&) {
50 return std::make_tuple(f(std::get<I>(std::forward<Tuple>(t)))...);
51 }
52
53 template<size_t I, typename IndexSequence>
54 struct prepend;
55
56 template<size_t I, size_t... Is>
57 struct prepend<I, std::index_sequence<Is...>> {
58 using type = std::index_sequence<I, Is...>;
59 };
60
61 template<template<typename> class Filter, typename Tuple, typename IndexSequence>
62 struct tuple_filter;
63
64 template<template<typename> class Filter, typename T, typename... Ts, size_t I, size_t... Is>
65 struct tuple_filter<Filter, std::tuple<T, Ts...>, std::index_sequence<I, Is...>> {
66 using tail = typename tuple_filter<Filter, std::tuple<Ts...>, std::index_sequence<Is...>>::type;
67 using type = std::conditional_t<Filter<T>::value, typename prepend<I, tail>::type, tail>;
68 };
69
70 template<template<typename> class Filter>
71 struct tuple_filter<Filter, std::tuple<>, std::index_sequence<>> {
72 using type = std::index_sequence<>;
73 };
74
75 template<typename Tuple, size_t... I>
76 auto tuple_filter_helper(Tuple&& t, std::index_sequence<I...>&&) {
77 return std::make_tuple(std::get<I>(std::forward<Tuple>(t))...);
78 }
79
80 }
81 /// \endcond
82
83 /// \addtogroup utilities
84 /// @{
85
86 /// Applies type transformation to all types in tuple
87 ///
88 /// Member type `type` is set to a tuple type which is a result of applying
89 /// transformation `MapClass<T>::type` to each element `T` of the input tuple
90 /// type.
91 ///
92 /// \tparam MapClass class template defining type transformation
93 /// \tparam Tuple input tuple type
94 template<template<typename> class MapClass, typename Tuple>
95 struct tuple_map_types;
96
97 /// @}
98
99 template<template<typename> class MapClass, typename... Elements>
100 struct tuple_map_types<MapClass, std::tuple<Elements...>> {
101 using type = std::tuple<typename MapClass<Elements>::type...>;
102 };
103
104 /// \addtogroup utilities
105 /// @{
106
107 /// Filters elements in tuple by their type
108 ///
109 /// Returns a tuple containing only those elements which type `T` caused
110 /// expression `FilterClass<T>::value` to be true.
111 ///
112 /// \tparam FilterClass class template having an element value set to true for elements that
113 /// should be present in the result
114 /// \param t tuple to filter
115 /// \return a tuple contaning elements which type passed the test
116 template<template<typename> class FilterClass, typename... Elements>
117 auto tuple_filter_by_type(const std::tuple<Elements...>& t) {
118 using sequence = typename internal::tuple_filter<FilterClass, std::tuple<Elements...>,
119 std::index_sequence_for<Elements...>>::type;
120 return internal::tuple_filter_helper(t, sequence());
121 }
122 template<template<typename> class FilterClass, typename... Elements>
123 auto tuple_filter_by_type(std::tuple<Elements...>&& t) {
124 using sequence = typename internal::tuple_filter<FilterClass, std::tuple<Elements...>,
125 std::index_sequence_for<Elements...>>::type;
126 return internal::tuple_filter_helper(std::move(t), sequence());
127 }
128
129 /// Applies function to all elements in tuple
130 ///
131 /// Applies given function to all elements in the tuple and returns a tuple
132 /// of results.
133 ///
134 /// \param t original tuple
135 /// \param f function to apply
136 /// \return tuple of results returned by f for each element in t
137 template<typename Function, typename... Elements>
138 auto tuple_map(const std::tuple<Elements...>& t, Function&& f) {
139 return internal::tuple_map_helper(t, std::forward<Function>(f),
140 std::index_sequence_for<Elements...>());
141 }
142 template<typename Function, typename... Elements>
143 auto tuple_map(std::tuple<Elements...>&& t, Function&& f) {
144 return internal::tuple_map_helper(std::move(t), std::forward<Function>(f),
145 std::index_sequence_for<Elements...>());
146 }
147
148 /// Iterate over all elements in tuple
149 ///
150 /// Iterates over given tuple and calls the specified function for each of
151 /// it elements.
152 ///
153 /// \param t a tuple to iterate over
154 /// \param f function to call for each tuple element
155 template<typename Function, typename... Elements>
156 void tuple_for_each(const std::tuple<Elements...>& t, Function&& f) {
157 return internal::tuple_for_each_helper(t, std::forward<Function>(f),
158 std::index_sequence_for<Elements...>());
159 }
160 template<typename Function, typename... Elements>
161 void tuple_for_each(std::tuple<Elements...>& t, Function&& f) {
162 return internal::tuple_for_each_helper(t, std::forward<Function>(f),
163 std::index_sequence_for<Elements...>());
164 }
165 template<typename Function, typename... Elements>
166 void tuple_for_each(std::tuple<Elements...>&& t, Function&& f) {
167 return internal::tuple_for_each_helper(std::move(t), std::forward<Function>(f),
168 std::index_sequence_for<Elements...>());
169 }
170
171 /// @}
172
173 }