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 // * make_from_tuple<T> == std::make_from_tuple<T> 29 // 30 // This header file also provides the tag types `in_place_t`, `in_place_type_t`, 31 // and `in_place_index_t`, as well as the constant `in_place`, and 32 // `constexpr` `std::move()` and `std::forward()` implementations in C++11. 33 // 34 // References: 35 // 36 // https://en.cppreference.com/w/cpp/utility/integer_sequence 37 // https://en.cppreference.com/w/cpp/utility/apply 38 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html 39 40 #ifndef ABSL_UTILITY_UTILITY_H_ 41 #define ABSL_UTILITY_UTILITY_H_ 42 43 #include <cstddef> 44 #include <cstdlib> 45 #include <tuple> 46 #include <utility> 47 48 #include "absl/base/config.h" 49 #include "absl/base/internal/inline_variable.h" 50 #include "absl/base/internal/invoke.h" 51 #include "absl/meta/type_traits.h" 52 53 namespace absl { 54 ABSL_NAMESPACE_BEGIN 55 56 // integer_sequence 57 // 58 // Class template representing a compile-time integer sequence. An instantiation 59 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 60 // type through its template arguments (which is a common need when 61 // working with C++11 variadic templates). `absl::integer_sequence` is designed 62 // to be a drop-in replacement for C++14's `std::integer_sequence`. 63 // 64 // Example: 65 // 66 // template< class T, T... Ints > 67 // void user_function(integer_sequence<T, Ints...>); 68 // 69 // int main() 70 // { 71 // // user_function's `T` will be deduced to `int` and `Ints...` 72 // // will be deduced to `0, 1, 2, 3, 4`. 73 // user_function(make_integer_sequence<int, 5>()); 74 // } 75 template <typename T, T... Ints> 76 struct integer_sequence { 77 using value_type = T; sizeinteger_sequence78 static constexpr size_t size() noexcept { return sizeof...(Ints); } 79 }; 80 81 // index_sequence 82 // 83 // A helper template for an `integer_sequence` of `size_t`, 84 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's 85 // `std::index_sequence`. 86 template <size_t... Ints> 87 using index_sequence = integer_sequence<size_t, Ints...>; 88 89 namespace utility_internal { 90 91 template <typename Seq, size_t SeqSize, size_t Rem> 92 struct Extend; 93 94 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 95 template <typename T, T... Ints, size_t SeqSize> 96 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> { 97 using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>; 98 }; 99 100 template <typename T, T... Ints, size_t SeqSize> 101 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> { 102 using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>; 103 }; 104 105 // Recursion helper for 'make_integer_sequence<T, N>'. 106 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 107 template <typename T, size_t N> 108 struct Gen { 109 using type = 110 typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type; 111 }; 112 113 template <typename T> 114 struct Gen<T, 0> { 115 using type = integer_sequence<T>; 116 }; 117 118 template <typename T> 119 struct InPlaceTypeTag { 120 explicit InPlaceTypeTag() = delete; 121 InPlaceTypeTag(const InPlaceTypeTag&) = delete; 122 InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete; 123 }; 124 125 template <size_t I> 126 struct InPlaceIndexTag { 127 explicit InPlaceIndexTag() = delete; 128 InPlaceIndexTag(const InPlaceIndexTag&) = delete; 129 InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete; 130 }; 131 132 } // namespace utility_internal 133 134 // Compile-time sequences of integers 135 136 // make_integer_sequence 137 // 138 // This template alias is equivalent to 139 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 140 // replacement for C++14's `std::make_integer_sequence`. 141 template <typename T, T N> 142 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; 143 144 // make_index_sequence 145 // 146 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 147 // and is designed to be a drop-in replacement for C++14's 148 // `std::make_index_sequence`. 149 template <size_t N> 150 using make_index_sequence = make_integer_sequence<size_t, N>; 151 152 // index_sequence_for 153 // 154 // Converts a typename pack into an index sequence of the same length, and 155 // is designed to be a drop-in replacement for C++14's 156 // `std::index_sequence_for()` 157 template <typename... Ts> 158 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 159 160 // Tag types 161 162 #ifdef ABSL_USES_STD_OPTIONAL 163 164 using std::in_place_t; 165 using std::in_place; 166 167 #else // ABSL_USES_STD_OPTIONAL 168 169 // in_place_t 170 // 171 // Tag type used to specify in-place construction, such as with 172 // `absl::optional`, designed to be a drop-in replacement for C++17's 173 // `std::in_place_t`. 174 struct in_place_t {}; 175 176 ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {}); 177 178 #endif // ABSL_USES_STD_OPTIONAL 179 180 #if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT) 181 using std::in_place_type; 182 using std::in_place_type_t; 183 #else 184 185 // in_place_type_t 186 // 187 // Tag type used for in-place construction when the type to construct needs to 188 // be specified, such as with `absl::any`, designed to be a drop-in replacement 189 // for C++17's `std::in_place_type_t`. 190 template <typename T> 191 using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>); 192 193 template <typename T> 194 void in_place_type(utility_internal::InPlaceTypeTag<T>) {} 195 #endif // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT 196 197 #ifdef ABSL_USES_STD_VARIANT 198 using std::in_place_index; 199 using std::in_place_index_t; 200 #else 201 202 // in_place_index_t 203 // 204 // Tag type used for in-place construction when the type to construct needs to 205 // be specified, such as with `absl::any`, designed to be a drop-in replacement 206 // for C++17's `std::in_place_index_t`. 207 template <size_t I> 208 using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>); 209 210 template <size_t I> 211 void in_place_index(utility_internal::InPlaceIndexTag<I>) {} 212 #endif // ABSL_USES_STD_VARIANT 213 214 // Constexpr move and forward 215 216 // move() 217 // 218 // A constexpr version of `std::move()`, designed to be a drop-in replacement 219 // for C++14's `std::move()`. 220 template <typename T> 221 constexpr absl::remove_reference_t<T>&& move(T&& t) noexcept { 222 return static_cast<absl::remove_reference_t<T>&&>(t); 223 } 224 225 // forward() 226 // 227 // A constexpr version of `std::forward()`, designed to be a drop-in replacement 228 // for C++14's `std::forward()`. 229 template <typename T> 230 constexpr T&& forward( 231 absl::remove_reference_t<T>& t) noexcept { // NOLINT(runtime/references) 232 return static_cast<T&&>(t); 233 } 234 235 namespace utility_internal { 236 // Helper method for expanding tuple into a called method. 237 template <typename Functor, typename Tuple, std::size_t... Indexes> 238 auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>) 239 -> decltype(absl::base_internal::invoke( 240 absl::forward<Functor>(functor), 241 std::get<Indexes>(absl::forward<Tuple>(t))...)) { 242 return absl::base_internal::invoke( 243 absl::forward<Functor>(functor), 244 std::get<Indexes>(absl::forward<Tuple>(t))...); 245 } 246 247 } // namespace utility_internal 248 249 // apply 250 // 251 // Invokes a Callable using elements of a tuple as its arguments. 252 // Each element of the tuple corresponds to an argument of the call (in order). 253 // Both the Callable argument and the tuple argument are perfect-forwarded. 254 // For member-function Callables, the first tuple element acts as the `this` 255 // pointer. `absl::apply` is designed to be a drop-in replacement for C++17's 256 // `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`. 257 // 258 // Example: 259 // 260 // class Foo { 261 // public: 262 // void Bar(int); 263 // }; 264 // void user_function1(int, std::string); 265 // void user_function2(std::unique_ptr<Foo>); 266 // auto user_lambda = [](int, int) {}; 267 // 268 // int main() 269 // { 270 // std::tuple<int, std::string> tuple1(42, "bar"); 271 // // Invokes the first user function on int, std::string. 272 // absl::apply(&user_function1, tuple1); 273 // 274 // std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>()); 275 // // Invokes the user function that takes ownership of the unique 276 // // pointer. 277 // absl::apply(&user_function2, std::move(tuple2)); 278 // 279 // auto foo = absl::make_unique<Foo>(); 280 // std::tuple<Foo*, int> tuple3(foo.get(), 42); 281 // // Invokes the method Bar on foo with one argument, 42. 282 // absl::apply(&Foo::Bar, tuple3); 283 // 284 // std::tuple<int, int> tuple4(8, 9); 285 // // Invokes a lambda. 286 // absl::apply(user_lambda, tuple4); 287 // } 288 template <typename Functor, typename Tuple> 289 auto apply(Functor&& functor, Tuple&& t) 290 -> decltype(utility_internal::apply_helper( 291 absl::forward<Functor>(functor), absl::forward<Tuple>(t), 292 absl::make_index_sequence<std::tuple_size< 293 typename std::remove_reference<Tuple>::type>::value>{})) { 294 return utility_internal::apply_helper( 295 absl::forward<Functor>(functor), absl::forward<Tuple>(t), 296 absl::make_index_sequence<std::tuple_size< 297 typename std::remove_reference<Tuple>::type>::value>{}); 298 } 299 300 // exchange 301 // 302 // Replaces the value of `obj` with `new_value` and returns the old value of 303 // `obj`. `absl::exchange` is designed to be a drop-in replacement for C++14's 304 // `std::exchange`. 305 // 306 // Example: 307 // 308 // Foo& operator=(Foo&& other) { 309 // ptr1_ = absl::exchange(other.ptr1_, nullptr); 310 // int1_ = absl::exchange(other.int1_, -1); 311 // return *this; 312 // } 313 template <typename T, typename U = T> 314 T exchange(T& obj, U&& new_value) { 315 T old_value = absl::move(obj); 316 obj = absl::forward<U>(new_value); 317 return old_value; 318 } 319 320 namespace utility_internal { 321 template <typename T, typename Tuple, size_t... I> 322 T make_from_tuple_impl(Tuple&& tup, absl::index_sequence<I...>) { 323 return T(std::get<I>(std::forward<Tuple>(tup))...); 324 } 325 } // namespace utility_internal 326 327 // make_from_tuple 328 // 329 // Given the template parameter type `T` and a tuple of arguments 330 // `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by 331 // calling `T(arg0, arg1, ..., argN)`. 332 // 333 // Example: 334 // 335 // std::tuple<const char*, size_t> args("hello world", 5); 336 // auto s = absl::make_from_tuple<std::string>(args); 337 // assert(s == "hello"); 338 // 339 template <typename T, typename Tuple> 340 constexpr T make_from_tuple(Tuple&& tup) { 341 return utility_internal::make_from_tuple_impl<T>( 342 std::forward<Tuple>(tup), 343 absl::make_index_sequence< 344 std::tuple_size<absl::decay_t<Tuple>>::value>{}); 345 } 346 347 ABSL_NAMESPACE_END 348 } // namespace absl 349 350 #endif // ABSL_UTILITY_UTILITY_H_ 351