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.

141 lines
3.9KB

  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_VIEW_MAP_HPP
  14. #define RANGES_V3_VIEW_MAP_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <concepts/concepts.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/utility/static_const.hpp>
  20. #include <range/v3/view/transform.hpp>
  21. #include <range/v3/view/view.hpp>
  22. // TODO: Reuse subrange's pair_like concept here and have get_first and get_second
  23. // dispatch through get<>()
  24. namespace ranges
  25. {
  26. /// \cond
  27. namespace detail
  28. {
  29. template<typename T>
  30. constexpr T & get_first_second_helper(T & t, std::true_type) noexcept
  31. {
  32. return t;
  33. }
  34. template<typename T>
  35. constexpr auto get_first_second_helper(T & t, std::false_type) noexcept(
  36. std::is_nothrow_move_constructible<T>::value) -> CPP_ret(T)( //
  37. requires move_constructible<T>)
  38. {
  39. return std::move(t);
  40. }
  41. template<typename P, typename E>
  42. using get_first_second_tag = meta::bool_<std::is_lvalue_reference<P>::value ||
  43. std::is_lvalue_reference<E>::value>;
  44. struct get_first
  45. {
  46. // clang-format off
  47. template<typename Pair>
  48. constexpr auto CPP_auto_fun(operator())(Pair &&p)(const)
  49. (
  50. return get_first_second_helper(
  51. p.first,
  52. get_first_second_tag<Pair, decltype(p.first)>{})
  53. )
  54. // clang-format on
  55. };
  56. struct get_second
  57. {
  58. // clang-format off
  59. template<typename Pair>
  60. constexpr auto CPP_auto_fun(operator())(Pair &&p)(const)
  61. (
  62. return get_first_second_helper(
  63. p.second,
  64. get_first_second_tag<Pair, decltype(p.second)>{})
  65. )
  66. // clang-format on
  67. };
  68. // clang-format off
  69. CPP_def
  70. (
  71. template(typename T)
  72. concept kv_pair_like_,
  73. invocable<get_first const &, T> &&
  74. invocable<get_second const &, T>
  75. );
  76. // clang-format on
  77. } // namespace detail
  78. /// \endcond
  79. /// \addtogroup group-views
  80. /// @{
  81. namespace views
  82. {
  83. struct keys_fn
  84. {
  85. template<typename Rng>
  86. auto operator()(Rng && rng) const -> CPP_ret(keys_range_view<all_t<Rng>>)( //
  87. requires viewable_range<Rng> && input_range<Rng> &&
  88. detail::kv_pair_like_<range_reference_t<Rng>>)
  89. {
  90. return {all(static_cast<Rng &&>(rng)), detail::get_first{}};
  91. }
  92. };
  93. struct values_fn
  94. {
  95. template<typename Rng>
  96. auto operator()(Rng && rng) const -> CPP_ret(values_view<all_t<Rng>>)( //
  97. requires viewable_range<Rng> && input_range<Rng> &&
  98. detail::kv_pair_like_<range_reference_t<Rng>>)
  99. {
  100. return {all(static_cast<Rng &&>(rng)), detail::get_second{}};
  101. }
  102. };
  103. /// \relates keys_fn
  104. /// \ingroup group-views
  105. RANGES_INLINE_VARIABLE(view<keys_fn>, keys)
  106. /// \relates values_fn
  107. /// \ingroup group-views
  108. RANGES_INLINE_VARIABLE(view<values_fn>, values)
  109. } // namespace views
  110. namespace cpp20
  111. {
  112. namespace views
  113. {
  114. using ranges::views::keys;
  115. using ranges::views::values;
  116. } // namespace views
  117. // TODO(@cjdb): provide implementation for elements_view
  118. } // namespace cpp20
  119. /// @}
  120. } // namespace ranges
  121. #endif