/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_VIEW_MAP_HPP #define RANGES_V3_VIEW_MAP_HPP #include <utility> #include <meta/meta.hpp> #include <concepts/concepts.hpp> #include <range/v3/range_fwd.hpp> #include <range/v3/utility/static_const.hpp> #include <range/v3/view/transform.hpp> #include <range/v3/view/view.hpp> // TODO: Reuse subrange's pair_like concept here and have get_first and get_second // dispatch through get<>() namespace ranges { /// \cond namespace detail { template<typename T> constexpr T & get_first_second_helper(T & t, std::true_type) noexcept { return t; } template<typename T> constexpr auto get_first_second_helper(T & t, std::false_type) noexcept( std::is_nothrow_move_constructible<T>::value) -> CPP_ret(T)( // requires move_constructible<T>) { return std::move(t); } template<typename P, typename E> using get_first_second_tag = meta::bool_<std::is_lvalue_reference<P>::value || std::is_lvalue_reference<E>::value>; struct get_first { // clang-format off template<typename Pair> constexpr auto CPP_auto_fun(operator())(Pair &&p)(const) ( return get_first_second_helper( p.first, get_first_second_tag<Pair, decltype(p.first)>{}) ) // clang-format on }; struct get_second { // clang-format off template<typename Pair> constexpr auto CPP_auto_fun(operator())(Pair &&p)(const) ( return get_first_second_helper( p.second, get_first_second_tag<Pair, decltype(p.second)>{}) ) // clang-format on }; // clang-format off CPP_def ( template(typename T) concept kv_pair_like_, invocable<get_first const &, T> && invocable<get_second const &, T> ); // clang-format on } // namespace detail /// \endcond /// \addtogroup group-views /// @{ namespace views { struct keys_fn { template<typename Rng> auto operator()(Rng && rng) const -> CPP_ret(keys_range_view<all_t<Rng>>)( // requires viewable_range<Rng> && input_range<Rng> && detail::kv_pair_like_<range_reference_t<Rng>>) { return {all(static_cast<Rng &&>(rng)), detail::get_first{}}; } }; struct values_fn { template<typename Rng> auto operator()(Rng && rng) const -> CPP_ret(values_view<all_t<Rng>>)( // requires viewable_range<Rng> && input_range<Rng> && detail::kv_pair_like_<range_reference_t<Rng>>) { return {all(static_cast<Rng &&>(rng)), detail::get_second{}}; } }; /// \relates keys_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view<keys_fn>, keys) /// \relates values_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view<values_fn>, values) } // namespace views namespace cpp20 { namespace views { using ranges::views::keys; using ranges::views::values; } // namespace views // TODO(@cjdb): provide implementation for elements_view } // namespace cpp20 /// @} } // namespace ranges #endif