utility.h
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This header file contains C++11 versions of standard <utility> header
16 // abstractions available within C++14 and C++17, and are designed to be drop-in
17 // replacement for code compliant with C++14 and C++17.
18 //
19 // The following abstractions are defined:
20 //
21 // * integer_sequence<T, Ints...> == std::integer_sequence<T, Ints...>
22 // * index_sequence<Ints...> == std::index_sequence<Ints...>
23 // * make_integer_sequence<T, N> == std::make_integer_sequence<T, N>
24 // * make_index_sequence<N> == std::make_index_sequence<N>
25 // * index_sequence_for<Ts...> == std::index_sequence_for<Ts...>
26 // * apply<Functor, Tuple> == std::apply<Functor, Tuple>
27 // * exchange<T> == std::exchange<T>
28 //
29 // This header file also provides the tag types `in_place_t`, `in_place_type_t`,
30 // and `in_place_index_t`, as well as the constant `in_place`, and
31 // `constexpr` `std::move()` and `std::forward()` implementations in C++11.
32 //
33 // References:
34 //
35 // https://en.cppreference.com/w/cpp/utility/integer_sequence
36 // https://en.cppreference.com/w/cpp/utility/apply
37 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
38 
39 #ifndef ABSL_UTILITY_UTILITY_H_
40 #define ABSL_UTILITY_UTILITY_H_
41 
42 #include <cstddef>
43 #include <cstdlib>
44 #include <tuple>
45 #include <utility>
46 
47 #include "absl/base/config.h"
50 #include "absl/meta/type_traits.h"
51 
52 namespace absl {
53 
54 // integer_sequence
55 //
56 // Class template representing a compile-time integer sequence. An instantiation
57 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
58 // type through its template arguments (which is a common need when
59 // working with C++11 variadic templates). `absl::integer_sequence` is designed
60 // to be a drop-in replacement for C++14's `std::integer_sequence`.
61 //
62 // Example:
63 //
64 // template< class T, T... Ints >
65 // void user_function(integer_sequence<T, Ints...>);
66 //
67 // int main()
68 // {
69 // // user_function's `T` will be deduced to `int` and `Ints...`
70 // // will be deduced to `0, 1, 2, 3, 4`.
71 // user_function(make_integer_sequence<int, 5>());
72 // }
73 template <typename T, T... Ints>
75  using value_type = T;
76  static constexpr size_t size() noexcept { return sizeof...(Ints); }
77 };
78 
79 // index_sequence
80 //
81 // A helper template for an `integer_sequence` of `size_t`,
82 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
83 // `std::index_sequence`.
84 template <size_t... Ints>
85 using index_sequence = integer_sequence<size_t, Ints...>;
86 
87 namespace utility_internal {
88 
89 template <typename Seq, size_t SeqSize, size_t Rem>
90 struct Extend;
91 
92 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
93 template <typename T, T... Ints, size_t SeqSize>
94 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> {
95  using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
96 };
97 
98 template <typename T, T... Ints, size_t SeqSize>
99 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> {
100  using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
101 };
102 
103 // Recursion helper for 'make_integer_sequence<T, N>'.
104 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
105 template <typename T, size_t N>
106 struct Gen {
107  using type =
108  typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
109 };
110 
111 template <typename T>
112 struct Gen<T, 0> {
114 };
115 
116 template <typename T>
118  explicit InPlaceTypeTag() = delete;
119  InPlaceTypeTag(const InPlaceTypeTag&) = delete;
120  InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete;
121 };
122 
123 template <size_t I>
125  explicit InPlaceIndexTag() = delete;
126  InPlaceIndexTag(const InPlaceIndexTag&) = delete;
127  InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete;
128 };
129 
130 } // namespace utility_internal
131 
132 // Compile-time sequences of integers
133 
134 // make_integer_sequence
135 //
136 // This template alias is equivalent to
137 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
138 // replacement for C++14's `std::make_integer_sequence`.
139 template <typename T, T N>
141 
142 // make_index_sequence
143 //
144 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
145 // and is designed to be a drop-in replacement for C++14's
146 // `std::make_index_sequence`.
147 template <size_t N>
149 
150 // index_sequence_for
151 //
152 // Converts a typename pack into an index sequence of the same length, and
153 // is designed to be a drop-in replacement for C++14's
154 // `std::index_sequence_for()`
155 template <typename... Ts>
157 
158 // Tag types
159 
160 #ifdef ABSL_HAVE_STD_OPTIONAL
161 
162 using std::in_place_t;
163 using std::in_place;
164 
165 #else // ABSL_HAVE_STD_OPTIONAL
166 
167 // in_place_t
168 //
169 // Tag type used to specify in-place construction, such as with
170 // `absl::optional`, designed to be a drop-in replacement for C++17's
171 // `std::in_place_t`.
172 struct in_place_t {};
173 
175 
176 #endif // ABSL_HAVE_STD_OPTIONAL
177 
178 #if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT)
179 using std::in_place_type;
181 #else
182 
183 // in_place_type_t
184 //
185 // Tag type used for in-place construction when the type to construct needs to
186 // be specified, such as with `absl::any`, designed to be a drop-in replacement
187 // for C++17's `std::in_place_type_t`.
188 template <typename T>
190 
191 template <typename T>
193 #endif // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT
194 
195 #ifdef ABSL_HAVE_STD_VARIANT
196 using std::in_place_index;
198 #else
199 
200 // in_place_index_t
201 //
202 // Tag type used for in-place construction when the type to construct needs to
203 // be specified, such as with `absl::any`, designed to be a drop-in replacement
204 // for C++17's `std::in_place_index_t`.
205 template <size_t I>
207 
208 template <size_t I>
210 #endif // ABSL_HAVE_STD_VARIANT
211 
212 // Constexpr move and forward
213 
214 // move()
215 //
216 // A constexpr version of `std::move()`, designed to be a drop-in replacement
217 // for C++14's `std::move()`.
218 template <typename T>
219 constexpr absl::remove_reference_t<T>&& move(T&& t) noexcept {
220  return static_cast<absl::remove_reference_t<T>&&>(t);
221 }
222 
223 // forward()
224 //
225 // A constexpr version of `std::forward()`, designed to be a drop-in replacement
226 // for C++14's `std::forward()`.
227 template <typename T>
228 constexpr T&& forward(
229  absl::remove_reference_t<T>& t) noexcept { // NOLINT(runtime/references)
230  return static_cast<T&&>(t);
231 }
232 
233 namespace utility_internal {
234 // Helper method for expanding tuple into a called method.
235 template <typename Functor, typename Tuple, std::size_t... Indexes>
236 auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
237  -> decltype(absl::base_internal::Invoke(
238  absl::forward<Functor>(functor),
239  std::get<Indexes>(absl::forward<Tuple>(t))...)) {
241  absl::forward<Functor>(functor),
242  std::get<Indexes>(absl::forward<Tuple>(t))...);
243 }
244 
245 } // namespace utility_internal
246 
247 // apply
248 //
249 // Invokes a Callable using elements of a tuple as its arguments.
250 // Each element of the tuple corresponds to an argument of the call (in order).
251 // Both the Callable argument and the tuple argument are perfect-forwarded.
252 // For member-function Callables, the first tuple element acts as the `this`
253 // pointer. `absl::apply` is designed to be a drop-in replacement for C++17's
254 // `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`.
255 //
256 // Example:
257 //
258 // class Foo {
259 // public:
260 // void Bar(int);
261 // };
262 // void user_function1(int, std::string);
263 // void user_function2(std::unique_ptr<Foo>);
264 // auto user_lambda = [](int, int) {};
265 //
266 // int main()
267 // {
268 // std::tuple<int, std::string> tuple1(42, "bar");
269 // // Invokes the first user function on int, std::string.
270 // absl::apply(&user_function1, tuple1);
271 //
272 // std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
273 // // Invokes the user function that takes ownership of the unique
274 // // pointer.
275 // absl::apply(&user_function2, std::move(tuple2));
276 //
277 // auto foo = absl::make_unique<Foo>();
278 // std::tuple<Foo*, int> tuple3(foo.get(), 42);
279 // // Invokes the method Bar on foo with one argument, 42.
280 // absl::apply(&Foo::Bar, tuple3);
281 //
282 // std::tuple<int, int> tuple4(8, 9);
283 // // Invokes a lambda.
284 // absl::apply(user_lambda, tuple4);
285 // }
286 template <typename Functor, typename Tuple>
287 auto apply(Functor&& functor, Tuple&& t)
288  -> decltype(utility_internal::apply_helper(
289  absl::forward<Functor>(functor), absl::forward<Tuple>(t),
290  absl::make_index_sequence<std::tuple_size<
291  typename std::remove_reference<Tuple>::type>::value>{})) {
293  absl::forward<Functor>(functor), absl::forward<Tuple>(t),
294  absl::make_index_sequence<std::tuple_size<
295  typename std::remove_reference<Tuple>::type>::value>{});
296 }
297 
298 // exchange
299 //
300 // Replaces the value of `obj` with `new_value` and returns the old value of
301 // `obj`. `absl::exchange` is designed to be a drop-in replacement for C++14's
302 // `std::exchange`.
303 //
304 // Example:
305 //
306 // Foo& operator=(Foo&& other) {
307 // ptr1_ = absl::exchange(other.ptr1_, nullptr);
308 // int1_ = absl::exchange(other.int1_, -1);
309 // return *this;
310 // }
311 template <typename T, typename U = T>
312 T exchange(T& obj, U&& new_value) {
313  T old_value = absl::move(obj);
314  obj = absl::forward<U>(new_value);
315  return old_value;
316 }
317 
318 } // namespace absl
319 
320 #endif // ABSL_UTILITY_UTILITY_H_
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: utility.h:228
InvokeT< F, Args... > Invoke(F &&f, Args &&...args)
Definition: invoke.h:181
typename std::remove_reference< T >::type remove_reference_t
Definition: type_traits.h:513
auto apply_helper(Functor &&functor, Tuple &&t, index_sequence< Indexes... >) -> decltype(absl::base_internal::Invoke(absl::forward< Functor >(functor), std::get< Indexes >(absl::forward< Tuple >(t))...))
Definition: utility.h:236
int old_value
Definition: output.cc:29
void in_place_type(utility_internal::InPlaceTypeTag< T >)
Definition: utility.h:192
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: utility.h:189
make_integer_sequence< size_t, N > make_index_sequence
Definition: utility.h:148
Definition: algorithm.h:29
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition: utility.h:140
static constexpr size_t size() noexcept
Definition: utility.h:76
size_t value
auto apply(Functor &&functor, Tuple &&t) -> decltype(utility_internal::apply_helper(absl::forward< Functor >(functor), absl::forward< Tuple >(t), absl::make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >
Definition: utility.h:287
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition: utility.h:156
void(*)(utility_internal::InPlaceIndexTag< I >) in_place_index_t
Definition: utility.h:206
ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos,-1)
void in_place_index(utility_internal::InPlaceIndexTag< I >)
Definition: utility.h:209
typename Extend< typename Gen< T, N/2 >::type, N/2, N%2 >::type type
Definition: utility.h:108
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
T exchange(T &obj, U &&new_value)
Definition: utility.h:312


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:37