| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /// \file
- // Range v3 library
- //
- // Copyright Eric Niebler 2014-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_VIEW_HPP
- #define RANGES_V3_VIEW_VIEW_HPP
- #include <type_traits>
- #include <utility>
- #include <meta/meta.hpp>
- #include <range/v3/range_fwd.hpp>
- #include <range/v3/functional/compose.hpp>
- #include <range/v3/functional/concepts.hpp>
- #include <range/v3/functional/pipeable.hpp>
- #include <range/v3/functional/reference_wrapper.hpp>
- #include <range/v3/range/concepts.hpp>
- #include <range/v3/range/traits.hpp>
- #include <range/v3/utility/static_const.hpp>
- #include <range/v3/detail/prologue.hpp>
- namespace ranges
- {
- /// \addtogroup group-views
- /// @{
- /// \cond
- namespace detail
- {
- struct dereference_fn
- {
- // clang-format off
- template<typename I>
- constexpr auto CPP_auto_fun(operator())(I &&i) (const)
- (
- return *(I &&) i
- )
- // clang-format on
- };
- struct view_closure_base_
- {};
- } // namespace detail
- /// \endcond
- // clang-format off
- /// \concept simple_view_impl_
- /// \brief The \c simple_view_impl_ concept
- template(typename Rng)(
- concept (simple_view_impl_)(Rng),
- same_as<iterator_t<Rng>, iterator_t<Rng const>> AND
- same_as<sentinel_t<Rng>, sentinel_t<Rng const>>);
- /// \concept simple_view_
- /// \brief The \c simple_view_ concept
- template<typename Rng>
- CPP_concept simple_view_ =
- view_<Rng> &&
- range<Rng const> &&
- CPP_concept_ref(ranges::simple_view_impl_, Rng);
- /// \concept invocable_view_closure_
- /// \brief The \c invocable_view_closure_ concept
- template(typename ViewFn, typename Rng)(
- concept (invocable_view_closure_)(ViewFn, Rng),
- !derived_from<invoke_result_t<ViewFn, Rng>, detail::view_closure_base_>);
- /// \concept invocable_view_closure
- /// \brief The \c invocable_view_closure concept
- template<typename ViewFn, typename Rng>
- CPP_concept invocable_view_closure =
- invocable<ViewFn, Rng> &&
- CPP_concept_ref(ranges::invocable_view_closure_, ViewFn, Rng);
- // clang-format on
- template<typename Rng>
- constexpr bool simple_view() noexcept
- {
- return (bool)simple_view_<Rng>;
- }
- struct make_view_closure_fn
- {
- template<typename Fun>
- constexpr views::view_closure<Fun> operator()(Fun fun) const
- {
- return views::view_closure<Fun>{static_cast<Fun &&>(fun)};
- }
- };
- /// \ingroup group-views
- /// \sa make_view_closure_fn
- RANGES_INLINE_VARIABLE(make_view_closure_fn, make_view_closure)
- namespace views
- {
- struct RANGES_STRUCT_WITH_ADL_BARRIER(view_closure_base)
- : detail::view_closure_base_
- {
- // Piping requires viewable_ranges. Pipeing a value into a closure
- // should not yield another closure.
- template(typename Rng, typename ViewFn)(
- requires viewable_range<Rng> AND
- invocable_view_closure<ViewFn, Rng>)
- friend constexpr auto operator|(Rng && rng, view_closure<ViewFn> vw)
- {
- return static_cast<ViewFn &&>(vw)(static_cast<Rng &&>(rng));
- }
- #ifndef RANGES_WORKAROUND_CLANG_43400
- // This overload is deleted because when piping a range into an
- // view, it must be moved in.
- template<typename Rng, typename ViewFn> // **************************
- friend constexpr auto // **************************
- operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
- // **** IF YOUR COMPILE *****
- -> CPP_broken_friend_ret(Rng)( // ****** BREAKS HERE *******
- requires range<Rng> && // **************************
- (!viewable_range<Rng>)) = delete; // **************************
- // **************************************************************************
- // * When piping a range into an adaptor, the range must satisfy the *
- // * "viewable_range" concept. A range is viewable when either or both *
- // * of these things are true: *
- // * - The range is an lvalue (not a temporary object), OR *
- // * - The range is a view (not a container). *
- // **************************************************************************
- #endif
- template<typename ViewFn, typename Pipeable>
- friend constexpr auto operator|(view_closure<ViewFn> vw, Pipeable pipe)
- -> CPP_broken_friend_ret(view_closure<composed<Pipeable, ViewFn>>)(
- requires (is_pipeable_v<Pipeable>))
- {
- return make_view_closure(
- compose(static_cast<Pipeable &&>(pipe), static_cast<ViewFn &&>(vw)));
- }
- };
- #ifdef RANGES_WORKAROUND_CLANG_43400
- namespace RANGES_ADL_BARRIER_FOR(view_closure_base)
- {
- // This overload is deleted because when piping a range into an
- // view, it must be moved in.
- template(typename Rng, typename ViewFn)( // ************************
- requires range<Rng> AND (!viewable_range<Rng>))// ************************
- constexpr Rng // ************************
- operator|(Rng &&, view_closure<ViewFn> const &) // ****** READ THIS *******
- = delete; // *** IF YOUR COMPILE ****
- // ***** BREAKS HERE ******
- // ************************
- // ************************
- // ***************************************************************************
- // * When piping a range into an adaptor, the range must satisfy the *
- // * "viewable_range" concept. A range is viewable when either or both *
- // * of these things are true: *
- // * - The range is an lvalue (not a temporary object), OR *
- // * - The range is a view (not a container). *
- // ***************************************************************************
- } // namespace )
- #endif // RANGES_WORKAROUND_CLANG_43400
- template<typename ViewFn>
- struct RANGES_EMPTY_BASES view_closure
- : view_closure_base
- , ViewFn
- {
- view_closure() = default;
- constexpr explicit view_closure(ViewFn fn)
- : ViewFn(static_cast<ViewFn &&>(fn))
- {}
- };
- /// \cond
- /// DEPRECATED STUFF
- struct view_access_
- {
- template<typename ViewFn>
- struct impl
- {
- // clang-format off
- template<typename... Ts, typename V = ViewFn>
- static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
- (
- return V::bind(static_cast<Ts &&>(ts)...)
- )
- // clang-format on
- };
- };
- using view_access RANGES_DEPRECATED(
- "view_access and views::view<> are deprecated. Please "
- "replace view<> with view_closure<> and discontinue use of view_access.") =
- view_access_;
- template<typename>
- struct old_view_;
- struct make_view_fn_
- {
- template<typename Fun>
- constexpr old_view_<Fun> operator()(Fun fun) const
- {
- return old_view_<Fun>{static_cast<Fun &&>(fun)};
- }
- };
- using make_view_fn RANGES_DEPRECATED(
- "make_view_fn is deprecated. Please use "
- "make_view_closure instead.") = make_view_fn_;
- namespace
- {
- RANGES_DEPRECATED(
- "make_view and views::view<> has been deprecated. Please switch to "
- "make_view_closure and views::view_closure.")
- RANGES_INLINE_VAR constexpr auto & make_view =
- static_const<make_view_fn_>::value;
- } // namespace
- template<typename ViewFn>
- struct old_view_ : pipeable_base
- {
- private:
- ViewFn vw_;
- friend pipeable_access;
- // Piping requires range arguments or lvalue containers.
- template(typename Rng, typename Vw)(
- requires viewable_range<Rng> AND invocable<ViewFn &, Rng>)
- static constexpr auto pipe(Rng && rng, Vw && v)
- {
- return v.vw_(static_cast<Rng &&>(rng));
- }
- public:
- old_view_() = default;
- constexpr explicit old_view_(ViewFn a) noexcept(
- std::is_nothrow_move_constructible<ViewFn>::value)
- : vw_(std::move(a))
- {}
- // Calling directly requires a viewable_range.
- template(typename Rng, typename... Rest)(
- requires viewable_range<Rng> AND invocable<ViewFn const &, Rng, Rest...>)
- constexpr invoke_result_t<ViewFn const &, Rng, Rest...> //
- operator()(Rng && rng, Rest &&... rest) const
- {
- return vw_(static_cast<Rng &&>(rng), static_cast<Rest &&>(rest)...);
- }
- // Currying overload.
- // clang-format off
- template<typename... Ts, typename V = ViewFn>
- constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const)
- (
- return make_view_fn_{}(
- view_access_::impl<V>::bind(vw_, static_cast<Ts &&>(ts)...))
- )
- // clang-format on
- };
- template<typename ViewFn>
- using view RANGES_DEPRECATED(
- "The views::view<> template is deprecated. Please switch to view_closure") =
- old_view_<ViewFn>;
- /// \endcond
- } // namespace views
- template<typename ViewFn>
- RANGES_INLINE_VAR constexpr bool is_pipeable_v<views::view_closure<ViewFn>> = true;
- /// @}
- } // namespace ranges
- #include <range/v3/detail/epilogue.hpp>
- #endif
|