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

191 lines
6.4KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_UTILITY_TUPLE_ALGORITHM_HPP
  14. #define RANGES_V3_UTILITY_TUPLE_ALGORITHM_HPP
  15. #include <initializer_list>
  16. #include <tuple>
  17. #include <type_traits>
  18. #include <utility>
  19. #include <meta/meta.hpp>
  20. #include <range/v3/range_fwd.hpp>
  21. #include <range/v3/detail/adl_get.hpp>
  22. #include <range/v3/functional/invoke.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. namespace ranges
  25. {
  26. /// \addtogroup group-utility
  27. /// @{
  28. template<typename Tup>
  29. using tuple_indices_t = meta::make_index_sequence<
  30. std::tuple_size<typename std::remove_reference<Tup>::type>::value>;
  31. struct tuple_apply_fn
  32. {
  33. // clang-format off
  34. private:
  35. template<typename Fun, typename Tup, std::size_t... Is>
  36. static constexpr auto CPP_auto_fun(impl)(Fun &&fun, Tup &&tup, meta::index_sequence<Is...>)
  37. (
  38. return invoke(static_cast<Fun &&>(fun),
  39. detail::adl_get<Is>(static_cast<Tup &&>(tup))...)
  40. )
  41. public:
  42. template<typename Fun, typename Tup>
  43. constexpr auto CPP_auto_fun(operator())(Fun &&fun, Tup &&tup)(const)
  44. (
  45. return tuple_apply_fn::impl(static_cast<Fun &&>(fun),
  46. static_cast<Tup &&>(tup),
  47. tuple_indices_t<Tup>{})
  48. )
  49. // clang-format on
  50. };
  51. /// \ingroup group-utility
  52. /// \sa `tuple_apply_fn`
  53. RANGES_INLINE_VARIABLE(tuple_apply_fn, tuple_apply)
  54. struct tuple_transform_fn
  55. {
  56. // clang-format off
  57. private:
  58. template<typename Tup, typename Fun, std::size_t... Is>
  59. static constexpr auto CPP_auto_fun(impl1)(Tup &&tup, Fun &fun, meta::index_sequence<Is...>)
  60. (
  61. return std::tuple<
  62. decltype(fun(detail::adl_get<Is>(static_cast<Tup &&>(tup))))...>{
  63. fun(detail::adl_get<Is>(static_cast<Tup &&>(
  64. tup)))...}
  65. )
  66. template<typename Tup0, typename Tup1, typename Fun, std::size_t... Is>
  67. static constexpr auto CPP_auto_fun(impl2)(Tup0 &&tup0, Tup1 &&tup1, Fun &fun,
  68. meta::index_sequence<Is...>)
  69. (
  70. return std::tuple<
  71. decltype(fun(detail::adl_get<Is>(static_cast<Tup0 &&>(tup0)),
  72. detail::adl_get<Is>(static_cast<Tup1 &&>(tup1))))...>{
  73. fun(detail::adl_get<Is>(static_cast<Tup0 &&>(tup0)),
  74. detail::adl_get<Is>(static_cast<Tup1 &&>(tup1)))...}
  75. )
  76. public:
  77. template<typename Tup, typename Fun>
  78. constexpr auto CPP_auto_fun(operator())(Tup &&tup, Fun fun)(const)
  79. (
  80. return tuple_transform_fn::impl1(
  81. static_cast<Tup &&>(tup), fun,
  82. tuple_indices_t<Tup>{})
  83. )
  84. template<typename Tup0, typename Tup1, typename Fun>
  85. constexpr auto CPP_auto_fun(operator())(Tup0 &&tup0, Tup1 &&tup1, Fun fun)(const)
  86. (
  87. return tuple_transform_fn::impl2(static_cast<Tup0 &&>(tup0),
  88. static_cast<Tup1 &&>(tup1), fun,
  89. tuple_indices_t<Tup0>{})
  90. )
  91. // clang-format on
  92. };
  93. /// \ingroup group-utility
  94. /// \sa `tuple_transform_fn`
  95. RANGES_INLINE_VARIABLE(tuple_transform_fn, tuple_transform)
  96. struct tuple_foldl_fn
  97. {
  98. private:
  99. template<typename Tup, typename Val, typename Fun>
  100. static constexpr Val impl(Tup &&, Val val, Fun &)
  101. {
  102. return val;
  103. }
  104. // clang-format off
  105. template<std::size_t I0, std::size_t... Is, typename Tup, typename Val,
  106. typename Fun, typename Impl = tuple_foldl_fn>
  107. static constexpr auto CPP_auto_fun(impl)(Tup &&tup, Val val, Fun &fun)
  108. (
  109. return Impl::template impl<Is...>(
  110. static_cast<Tup &&>(tup),
  111. fun(std::move(val), detail::adl_get<I0>(static_cast<Tup &&>(tup))),
  112. fun)
  113. )
  114. template<typename Tup, typename Val, typename Fun, std::size_t... Is>
  115. static constexpr auto CPP_auto_fun(impl2)(Tup &&tup, Val val, Fun &fun,
  116. meta::index_sequence<Is...>)
  117. (
  118. return tuple_foldl_fn::impl<Is...>(static_cast<Tup &&>(tup),
  119. std::move(val),
  120. fun)
  121. )
  122. public:
  123. template<typename Tup, typename Val, typename Fun>
  124. constexpr auto CPP_auto_fun(operator())(Tup &&tup, Val val, Fun fun)(const)
  125. (
  126. return tuple_foldl_fn::impl2(static_cast<Tup &&>(tup),
  127. std::move(val),
  128. fun,
  129. tuple_indices_t<Tup>{})
  130. )
  131. // clang-format on
  132. };
  133. /// \ingroup group-utility
  134. /// \sa `tuple_foldl_fn`
  135. RANGES_INLINE_VARIABLE(tuple_foldl_fn, tuple_foldl)
  136. struct tuple_for_each_fn
  137. {
  138. private:
  139. template<typename Tup, typename Fun, std::size_t... Is>
  140. static constexpr void impl(Tup && tup, Fun & fun, meta::index_sequence<Is...>)
  141. {
  142. (void)std::initializer_list<int>{
  143. ((void)fun(detail::adl_get<Is>(static_cast<Tup &&>(tup))), 42)...};
  144. }
  145. public:
  146. template<typename Tup, typename Fun>
  147. constexpr Fun operator()(Tup && tup, Fun fun) const
  148. {
  149. return tuple_for_each_fn::impl(
  150. static_cast<Tup &&>(tup), fun, tuple_indices_t<Tup>{}),
  151. fun;
  152. }
  153. };
  154. /// \ingroup group-utility
  155. /// \sa `tuple_for_each_fn`
  156. RANGES_INLINE_VARIABLE(tuple_for_each_fn, tuple_for_each)
  157. struct make_tuple_fn
  158. {
  159. // clang-format off
  160. template<typename... Ts>
  161. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const)
  162. (
  163. return std::make_tuple(static_cast<Ts &&>(ts)...)
  164. )
  165. // clang-format on
  166. };
  167. /// \ingroup group-utility
  168. /// \sa `make_tuple_fn`
  169. RANGES_INLINE_VARIABLE(make_tuple_fn, make_tuple)
  170. /// @}
  171. } // namespace ranges
  172. #endif