utility.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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++14 versions of standard <utility> header
  16. // abstractions available within 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. // * apply<Functor, Tuple> == std::apply<Functor, Tuple>
  22. // * exchange<T> == std::exchange<T>
  23. // * make_from_tuple<T> == std::make_from_tuple<T>
  24. //
  25. // This header file also provides the tag types `in_place_t`, `in_place_type_t`,
  26. // and `in_place_index_t`, as well as the constant `in_place`, and
  27. // `constexpr` `std::move()` and `std::forward()` implementations in C++11.
  28. //
  29. // References:
  30. //
  31. // https://en.cppreference.com/w/cpp/utility/apply
  32. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
  33. #ifndef ABSL_UTILITY_UTILITY_H_
  34. #define ABSL_UTILITY_UTILITY_H_
  35. #include <cstddef>
  36. #include <cstdlib>
  37. #include <tuple>
  38. #include <utility>
  39. #include "absl/base/config.h"
  40. #include "absl/base/internal/inline_variable.h"
  41. #include "absl/base/internal/invoke.h"
  42. #include "absl/meta/type_traits.h"
  43. namespace absl {
  44. ABSL_NAMESPACE_BEGIN
  45. // Historical note: Abseil once provided implementations of these
  46. // abstractions for platforms that had not yet provided them. Those
  47. // platforms are no longer supported. New code should simply use the
  48. // the ones from std directly.
  49. using std::exchange;
  50. using std::forward;
  51. using std::index_sequence;
  52. using std::index_sequence_for;
  53. using std::integer_sequence;
  54. using std::make_index_sequence;
  55. using std::make_integer_sequence;
  56. using std::move;
  57. namespace utility_internal {
  58. template <typename T>
  59. struct InPlaceTypeTag {
  60. explicit InPlaceTypeTag() = delete;
  61. InPlaceTypeTag(const InPlaceTypeTag&) = delete;
  62. InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete;
  63. };
  64. template <size_t I>
  65. struct InPlaceIndexTag {
  66. explicit InPlaceIndexTag() = delete;
  67. InPlaceIndexTag(const InPlaceIndexTag&) = delete;
  68. InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete;
  69. };
  70. } // namespace utility_internal
  71. // Tag types
  72. #ifdef ABSL_USES_STD_OPTIONAL
  73. using std::in_place_t;
  74. using std::in_place;
  75. #else // ABSL_USES_STD_OPTIONAL
  76. // in_place_t
  77. //
  78. // Tag type used to specify in-place construction, such as with
  79. // `absl::optional`, designed to be a drop-in replacement for C++17's
  80. // `std::in_place_t`.
  81. struct in_place_t {};
  82. ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
  83. #endif // ABSL_USES_STD_OPTIONAL
  84. #if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT)
  85. using std::in_place_type;
  86. using std::in_place_type_t;
  87. #else
  88. // in_place_type_t
  89. //
  90. // Tag type used for in-place construction when the type to construct needs to
  91. // be specified, such as with `absl::any`, designed to be a drop-in replacement
  92. // for C++17's `std::in_place_type_t`.
  93. template <typename T>
  94. using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>);
  95. template <typename T>
  96. void in_place_type(utility_internal::InPlaceTypeTag<T>) {}
  97. #endif // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT
  98. #ifdef ABSL_USES_STD_VARIANT
  99. using std::in_place_index;
  100. using std::in_place_index_t;
  101. #else
  102. // in_place_index_t
  103. //
  104. // Tag type used for in-place construction when the type to construct needs to
  105. // be specified, such as with `absl::any`, designed to be a drop-in replacement
  106. // for C++17's `std::in_place_index_t`.
  107. template <size_t I>
  108. using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>);
  109. template <size_t I>
  110. void in_place_index(utility_internal::InPlaceIndexTag<I>) {}
  111. #endif // ABSL_USES_STD_VARIANT
  112. namespace utility_internal {
  113. // Helper method for expanding tuple into a called method.
  114. template <typename Functor, typename Tuple, std::size_t... Indexes>
  115. auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
  116. -> decltype(absl::base_internal::invoke(
  117. absl::forward<Functor>(functor),
  118. std::get<Indexes>(absl::forward<Tuple>(t))...)) {
  119. return absl::base_internal::invoke(
  120. absl::forward<Functor>(functor),
  121. std::get<Indexes>(absl::forward<Tuple>(t))...);
  122. }
  123. } // namespace utility_internal
  124. // apply
  125. //
  126. // Invokes a Callable using elements of a tuple as its arguments.
  127. // Each element of the tuple corresponds to an argument of the call (in order).
  128. // Both the Callable argument and the tuple argument are perfect-forwarded.
  129. // For member-function Callables, the first tuple element acts as the `this`
  130. // pointer. `absl::apply` is designed to be a drop-in replacement for C++17's
  131. // `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`.
  132. //
  133. // Example:
  134. //
  135. // class Foo {
  136. // public:
  137. // void Bar(int);
  138. // };
  139. // void user_function1(int, std::string);
  140. // void user_function2(std::unique_ptr<Foo>);
  141. // auto user_lambda = [](int, int) {};
  142. //
  143. // int main()
  144. // {
  145. // std::tuple<int, std::string> tuple1(42, "bar");
  146. // // Invokes the first user function on int, std::string.
  147. // absl::apply(&user_function1, tuple1);
  148. //
  149. // std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
  150. // // Invokes the user function that takes ownership of the unique
  151. // // pointer.
  152. // absl::apply(&user_function2, std::move(tuple2));
  153. //
  154. // auto foo = absl::make_unique<Foo>();
  155. // std::tuple<Foo*, int> tuple3(foo.get(), 42);
  156. // // Invokes the method Bar on foo with one argument, 42.
  157. // absl::apply(&Foo::Bar, tuple3);
  158. //
  159. // std::tuple<int, int> tuple4(8, 9);
  160. // // Invokes a lambda.
  161. // absl::apply(user_lambda, tuple4);
  162. // }
  163. template <typename Functor, typename Tuple>
  164. auto apply(Functor&& functor, Tuple&& t)
  165. -> decltype(utility_internal::apply_helper(
  166. absl::forward<Functor>(functor), absl::forward<Tuple>(t),
  167. absl::make_index_sequence<std::tuple_size<
  168. typename std::remove_reference<Tuple>::type>::value>{})) {
  169. return utility_internal::apply_helper(
  170. absl::forward<Functor>(functor), absl::forward<Tuple>(t),
  171. absl::make_index_sequence<std::tuple_size<
  172. typename std::remove_reference<Tuple>::type>::value>{});
  173. }
  174. namespace utility_internal {
  175. template <typename T, typename Tuple, size_t... I>
  176. T make_from_tuple_impl(Tuple&& tup, absl::index_sequence<I...>) {
  177. return T(std::get<I>(std::forward<Tuple>(tup))...);
  178. }
  179. } // namespace utility_internal
  180. // make_from_tuple
  181. //
  182. // Given the template parameter type `T` and a tuple of arguments
  183. // `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by
  184. // calling `T(arg0, arg1, ..., argN)`.
  185. //
  186. // Example:
  187. //
  188. // std::tuple<const char*, size_t> args("hello world", 5);
  189. // auto s = absl::make_from_tuple<std::string>(args);
  190. // assert(s == "hello");
  191. //
  192. template <typename T, typename Tuple>
  193. constexpr T make_from_tuple(Tuple&& tup) {
  194. return utility_internal::make_from_tuple_impl<T>(
  195. std::forward<Tuple>(tup),
  196. absl::make_index_sequence<
  197. std::tuple_size<absl::decay_t<Tuple>>::value>{});
  198. }
  199. ABSL_NAMESPACE_END
  200. } // namespace absl
  201. #endif // ABSL_UTILITY_UTILITY_H_