utility.h
Go to the documentation of this file.
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_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:16