map.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. #include <range/v3/detail/prologue.hpp>
  23. // TODO: Reuse subrange's pair_like concept here and have get_first and get_second
  24. // dispatch through get<>()
  25. namespace ranges
  26. {
  27. /// \cond
  28. namespace detail
  29. {
  30. template<typename T>
  31. constexpr T & get_first_second_helper(T & t, std::true_type) noexcept
  32. {
  33. return t;
  34. }
  35. template(typename T)(
  36. requires move_constructible<T>)
  37. constexpr T get_first_second_helper(T & t, std::false_type) //
  38. noexcept(std::is_nothrow_move_constructible<T>::value)
  39. {
  40. return std::move(t);
  41. }
  42. template<typename P, typename E>
  43. using get_first_second_tag = meta::bool_<std::is_lvalue_reference<P>::value ||
  44. std::is_lvalue_reference<E>::value>;
  45. struct get_first
  46. {
  47. // clang-format off
  48. template<typename Pair>
  49. constexpr auto CPP_auto_fun(operator())(Pair &&p)(const)
  50. (
  51. return get_first_second_helper(
  52. p.first,
  53. get_first_second_tag<Pair, decltype(p.first)>{})
  54. )
  55. // clang-format on
  56. };
  57. struct get_second
  58. {
  59. // clang-format off
  60. template<typename Pair>
  61. constexpr auto CPP_auto_fun(operator())(Pair &&p)(const)
  62. (
  63. return get_first_second_helper(
  64. p.second,
  65. get_first_second_tag<Pair, decltype(p.second)>{})
  66. )
  67. // clang-format on
  68. };
  69. // clang-format off
  70. /// \concept kv_pair_like_
  71. /// \brief The \c kv_pair_like_ concept
  72. template<typename T>
  73. CPP_concept kv_pair_like_ =
  74. invocable<get_first const &, T> &&
  75. invocable<get_second const &, T>;
  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. requires viewable_range<Rng> AND input_range<Rng> AND
  87. detail::kv_pair_like_<range_reference_t<Rng>>)
  88. keys_range_view<all_t<Rng>> operator()(Rng && rng) const
  89. {
  90. return {all(static_cast<Rng &&>(rng)), detail::get_first{}};
  91. }
  92. };
  93. struct values_fn
  94. {
  95. template(typename Rng)(
  96. requires viewable_range<Rng> AND input_range<Rng> AND
  97. detail::kv_pair_like_<range_reference_t<Rng>>)
  98. values_view<all_t<Rng>> operator()(Rng && rng) const
  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_closure<keys_fn>, keys)
  106. /// \relates values_fn
  107. /// \ingroup group-views
  108. RANGES_INLINE_VARIABLE(view_closure<values_fn>, values)
  109. } // namespace views
  110. template<typename Rng>
  111. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<keys_range_view<Rng>> =
  112. enable_borrowed_range<Rng>;
  113. template<typename Rng>
  114. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<values_view<Rng>> =
  115. enable_borrowed_range<Rng>;
  116. namespace cpp20
  117. {
  118. namespace views
  119. {
  120. using ranges::views::keys;
  121. using ranges::views::values;
  122. } // namespace views
  123. // TODO(@cjdb): provide implementation for elements_view
  124. } // namespace cpp20
  125. /// @}
  126. } // namespace ranges
  127. #include <range/v3/detail/epilogue.hpp>
  128. #endif