]>
Commit | Line | Data |
---|---|---|
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 | ||
27 | namespace seastar { | |
28 | ||
29 | /// \cond internal | |
30 | namespace internal { | |
31 | ||
32 | template<typename Tuple> | |
33 | Tuple untuple(Tuple t) { | |
9f95a23c | 34 | return t; |
11fdf7f2 TL |
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 | } |