00001 // Copyright 2017 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 // 00015 // This header file contains C++11 versions of standard <utility> header 00016 // abstractions available within C++14 and C++17, and are designed to be drop-in 00017 // replacement for code compliant with C++14 and C++17. 00018 // 00019 // The following abstractions are defined: 00020 // 00021 // * integer_sequence<T, Ints...> == std::integer_sequence<T, Ints...> 00022 // * index_sequence<Ints...> == std::index_sequence<Ints...> 00023 // * make_integer_sequence<T, N> == std::make_integer_sequence<T, N> 00024 // * make_index_sequence<N> == std::make_index_sequence<N> 00025 // * index_sequence_for<Ts...> == std::index_sequence_for<Ts...> 00026 // * apply<Functor, Tuple> == std::apply<Functor, Tuple> 00027 // * exchange<T> == std::exchange<T> 00028 // 00029 // This header file also provides the tag types `in_place_t`, `in_place_type_t`, 00030 // and `in_place_index_t`, as well as the constant `in_place`, and 00031 // `constexpr` `std::move()` and `std::forward()` implementations in C++11. 00032 // 00033 // References: 00034 // 00035 // https://en.cppreference.com/w/cpp/utility/integer_sequence 00036 // https://en.cppreference.com/w/cpp/utility/apply 00037 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html 00038 00039 #ifndef ABSL_UTILITY_UTILITY_H_ 00040 #define ABSL_UTILITY_UTILITY_H_ 00041 00042 #include <cstddef> 00043 #include <cstdlib> 00044 #include <tuple> 00045 #include <utility> 00046 00047 #include "absl/base/config.h" 00048 #include "absl/base/internal/inline_variable.h" 00049 #include "absl/base/internal/invoke.h" 00050 #include "absl/meta/type_traits.h" 00051 00052 namespace absl { 00053 00054 // integer_sequence 00055 // 00056 // Class template representing a compile-time integer sequence. An instantiation 00057 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 00058 // type through its template arguments (which is a common need when 00059 // working with C++11 variadic templates). `absl::integer_sequence` is designed 00060 // to be a drop-in replacement for C++14's `std::integer_sequence`. 00061 // 00062 // Example: 00063 // 00064 // template< class T, T... Ints > 00065 // void user_function(integer_sequence<T, Ints...>); 00066 // 00067 // int main() 00068 // { 00069 // // user_function's `T` will be deduced to `int` and `Ints...` 00070 // // will be deduced to `0, 1, 2, 3, 4`. 00071 // user_function(make_integer_sequence<int, 5>()); 00072 // } 00073 template <typename T, T... Ints> 00074 struct integer_sequence { 00075 using value_type = T; 00076 static constexpr size_t size() noexcept { return sizeof...(Ints); } 00077 }; 00078 00079 // index_sequence 00080 // 00081 // A helper template for an `integer_sequence` of `size_t`, 00082 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's 00083 // `std::index_sequence`. 00084 template <size_t... Ints> 00085 using index_sequence = integer_sequence<size_t, Ints...>; 00086 00087 namespace utility_internal { 00088 00089 template <typename Seq, size_t SeqSize, size_t Rem> 00090 struct Extend; 00091 00092 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 00093 template <typename T, T... Ints, size_t SeqSize> 00094 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> { 00095 using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>; 00096 }; 00097 00098 template <typename T, T... Ints, size_t SeqSize> 00099 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> { 00100 using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>; 00101 }; 00102 00103 // Recursion helper for 'make_integer_sequence<T, N>'. 00104 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 00105 template <typename T, size_t N> 00106 struct Gen { 00107 using type = 00108 typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type; 00109 }; 00110 00111 template <typename T> 00112 struct Gen<T, 0> { 00113 using type = integer_sequence<T>; 00114 }; 00115 00116 template <typename T> 00117 struct InPlaceTypeTag { 00118 explicit InPlaceTypeTag() = delete; 00119 InPlaceTypeTag(const InPlaceTypeTag&) = delete; 00120 InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete; 00121 }; 00122 00123 template <size_t I> 00124 struct InPlaceIndexTag { 00125 explicit InPlaceIndexTag() = delete; 00126 InPlaceIndexTag(const InPlaceIndexTag&) = delete; 00127 InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete; 00128 }; 00129 00130 } // namespace utility_internal 00131 00132 // Compile-time sequences of integers 00133 00134 // make_integer_sequence 00135 // 00136 // This template alias is equivalent to 00137 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 00138 // replacement for C++14's `std::make_integer_sequence`. 00139 template <typename T, T N> 00140 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; 00141 00142 // make_index_sequence 00143 // 00144 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 00145 // and is designed to be a drop-in replacement for C++14's 00146 // `std::make_index_sequence`. 00147 template <size_t N> 00148 using make_index_sequence = make_integer_sequence<size_t, N>; 00149 00150 // index_sequence_for 00151 // 00152 // Converts a typename pack into an index sequence of the same length, and 00153 // is designed to be a drop-in replacement for C++14's 00154 // `std::index_sequence_for()` 00155 template <typename... Ts> 00156 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 00157 00158 // Tag types 00159 00160 #ifdef ABSL_HAVE_STD_OPTIONAL 00161 00162 using std::in_place_t; 00163 using std::in_place; 00164 00165 #else // ABSL_HAVE_STD_OPTIONAL 00166 00167 // in_place_t 00168 // 00169 // Tag type used to specify in-place construction, such as with 00170 // `absl::optional`, designed to be a drop-in replacement for C++17's 00171 // `std::in_place_t`. 00172 struct in_place_t {}; 00173 00174 ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {}); 00175 00176 #endif // ABSL_HAVE_STD_OPTIONAL 00177 00178 #if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT) 00179 using std::in_place_type; 00180 using std::in_place_type_t; 00181 #else 00182 00183 // in_place_type_t 00184 // 00185 // Tag type used for in-place construction when the type to construct needs to 00186 // be specified, such as with `absl::any`, designed to be a drop-in replacement 00187 // for C++17's `std::in_place_type_t`. 00188 template <typename T> 00189 using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>); 00190 00191 template <typename T> 00192 void in_place_type(utility_internal::InPlaceTypeTag<T>) {} 00193 #endif // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT 00194 00195 #ifdef ABSL_HAVE_STD_VARIANT 00196 using std::in_place_index; 00197 using std::in_place_index_t; 00198 #else 00199 00200 // in_place_index_t 00201 // 00202 // Tag type used for in-place construction when the type to construct needs to 00203 // be specified, such as with `absl::any`, designed to be a drop-in replacement 00204 // for C++17's `std::in_place_index_t`. 00205 template <size_t I> 00206 using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>); 00207 00208 template <size_t I> 00209 void in_place_index(utility_internal::InPlaceIndexTag<I>) {} 00210 #endif // ABSL_HAVE_STD_VARIANT 00211 00212 // Constexpr move and forward 00213 00214 // move() 00215 // 00216 // A constexpr version of `std::move()`, designed to be a drop-in replacement 00217 // for C++14's `std::move()`. 00218 template <typename T> 00219 constexpr absl::remove_reference_t<T>&& move(T&& t) noexcept { 00220 return static_cast<absl::remove_reference_t<T>&&>(t); 00221 } 00222 00223 // forward() 00224 // 00225 // A constexpr version of `std::forward()`, designed to be a drop-in replacement 00226 // for C++14's `std::forward()`. 00227 template <typename T> 00228 constexpr T&& forward( 00229 absl::remove_reference_t<T>& t) noexcept { // NOLINT(runtime/references) 00230 return static_cast<T&&>(t); 00231 } 00232 00233 namespace utility_internal { 00234 // Helper method for expanding tuple into a called method. 00235 template <typename Functor, typename Tuple, std::size_t... Indexes> 00236 auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>) 00237 -> decltype(absl::base_internal::Invoke( 00238 absl::forward<Functor>(functor), 00239 std::get<Indexes>(absl::forward<Tuple>(t))...)) { 00240 return absl::base_internal::Invoke( 00241 absl::forward<Functor>(functor), 00242 std::get<Indexes>(absl::forward<Tuple>(t))...); 00243 } 00244 00245 } // namespace utility_internal 00246 00247 // apply 00248 // 00249 // Invokes a Callable using elements of a tuple as its arguments. 00250 // Each element of the tuple corresponds to an argument of the call (in order). 00251 // Both the Callable argument and the tuple argument are perfect-forwarded. 00252 // For member-function Callables, the first tuple element acts as the `this` 00253 // pointer. `absl::apply` is designed to be a drop-in replacement for C++17's 00254 // `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`. 00255 // 00256 // Example: 00257 // 00258 // class Foo { 00259 // public: 00260 // void Bar(int); 00261 // }; 00262 // void user_function1(int, std::string); 00263 // void user_function2(std::unique_ptr<Foo>); 00264 // auto user_lambda = [](int, int) {}; 00265 // 00266 // int main() 00267 // { 00268 // std::tuple<int, std::string> tuple1(42, "bar"); 00269 // // Invokes the first user function on int, std::string. 00270 // absl::apply(&user_function1, tuple1); 00271 // 00272 // std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>()); 00273 // // Invokes the user function that takes ownership of the unique 00274 // // pointer. 00275 // absl::apply(&user_function2, std::move(tuple2)); 00276 // 00277 // auto foo = absl::make_unique<Foo>(); 00278 // std::tuple<Foo*, int> tuple3(foo.get(), 42); 00279 // // Invokes the method Bar on foo with one argument, 42. 00280 // absl::apply(&Foo::Bar, tuple3); 00281 // 00282 // std::tuple<int, int> tuple4(8, 9); 00283 // // Invokes a lambda. 00284 // absl::apply(user_lambda, tuple4); 00285 // } 00286 template <typename Functor, typename Tuple> 00287 auto apply(Functor&& functor, Tuple&& t) 00288 -> decltype(utility_internal::apply_helper( 00289 absl::forward<Functor>(functor), absl::forward<Tuple>(t), 00290 absl::make_index_sequence<std::tuple_size< 00291 typename std::remove_reference<Tuple>::type>::value>{})) { 00292 return utility_internal::apply_helper( 00293 absl::forward<Functor>(functor), absl::forward<Tuple>(t), 00294 absl::make_index_sequence<std::tuple_size< 00295 typename std::remove_reference<Tuple>::type>::value>{}); 00296 } 00297 00298 // exchange 00299 // 00300 // Replaces the value of `obj` with `new_value` and returns the old value of 00301 // `obj`. `absl::exchange` is designed to be a drop-in replacement for C++14's 00302 // `std::exchange`. 00303 // 00304 // Example: 00305 // 00306 // Foo& operator=(Foo&& other) { 00307 // ptr1_ = absl::exchange(other.ptr1_, nullptr); 00308 // int1_ = absl::exchange(other.int1_, -1); 00309 // return *this; 00310 // } 00311 template <typename T, typename U = T> 00312 T exchange(T& obj, U&& new_value) { 00313 T old_value = absl::move(obj); 00314 obj = absl::forward<U>(new_value); 00315 return old_value; 00316 } 00317 00318 } // namespace absl 00319 00320 #endif // ABSL_UTILITY_UTILITY_H_