utility.h 11 KB

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