You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

utility.h 13 kB

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