]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
11fdf7f2
TL
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
27namespace seastar {
28
29/// \cond internal
30namespace internal {
31
32template<typename Tuple>
33Tuple untuple(Tuple t) {
9f95a23c 34 return t;
11fdf7f2
TL
35}
36
37template<typename T>
38T untuple(std::tuple<T> t) {
39 return std::get<0>(std::move(t));
40}
41
42template<typename Tuple, typename Function, size_t... I>
43void 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
48template<typename Tuple, typename MapFunction, size_t... I>
49auto 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
53template<size_t I, typename IndexSequence>
54struct prepend;
55
56template<size_t I, size_t... Is>
57struct prepend<I, std::index_sequence<Is...>> {
58 using type = std::index_sequence<I, Is...>;
59};
60
61template<template<typename> class Filter, typename Tuple, typename IndexSequence>
62struct tuple_filter;
63
64template<template<typename> class Filter, typename T, typename... Ts, size_t I, size_t... Is>
65struct 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
70template<template<typename> class Filter>
71struct tuple_filter<Filter, std::tuple<>, std::index_sequence<>> {
72 using type = std::index_sequence<>;
73};
74
75template<typename Tuple, size_t... I>
76auto 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
94template<template<typename> class MapClass, typename Tuple>
95struct tuple_map_types;
96
97/// @}
98
99template<template<typename> class MapClass, typename... Elements>
100struct 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
116template<template<typename> class FilterClass, typename... Elements>
117auto 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}
122template<template<typename> class FilterClass, typename... Elements>
123auto 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
137template<typename Function, typename... Elements>
138auto 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}
142template<typename Function, typename... Elements>
143auto 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
155template<typename Function, typename... Elements>
156void 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}
160template<typename Function, typename... Elements>
161void 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}
165template<typename Function, typename... Elements>
166void 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}