#ifndef SPROUT_RANGE_ADAPTOR_PIPED_HPP #define SPROUT_RANGE_ADAPTOR_PIPED_HPP #include #include #include #include #include #include #include namespace sprout { namespace adaptors { namespace detail { template inline SPROUT_CONSTEXPR auto apply_adaptors_impl(Range&& range) -> decltype(sprout::forward(range)) { return sprout::forward(range); } template inline SPROUT_CONSTEXPR auto apply_adaptors_impl(Range&& range, Adaptor const& adaptor) -> decltype(sprout::forward(range) | adaptor) { return sprout::forward(range) | adaptor; } template inline SPROUT_CONSTEXPR auto apply_adaptors_impl(Range&& range, Adaptor const& adaptor, Tail const&... tail) -> decltype(sprout::adaptors::detail::apply_adaptors_impl(sprout::forward(range) | adaptor, tail...)) { return sprout::adaptors::detail::apply_adaptors_impl(sprout::forward(range) | adaptor, tail...); } } // namespace detail // // apply_adaptors // template SPROUT_CONSTEXPR auto apply_adaptors(Range&& range, Adaptors const&... adaptors) -> decltype(sprout::adaptors::detail::apply_adaptors_impl(sprout::forward(range), adaptors...)) { return sprout::adaptors::detail::apply_adaptors_impl(sprout::forward(range), adaptors...); } namespace detail { template SPROUT_CONSTEXPR auto apply_adaptors_tuple_impl(Range&& range, AdaptorsTuple const& adaptors, sprout::index_tuple) -> decltype(sprout::adaptors::apply_adaptors(sprout::forward(range), sprout::tuples::get(adaptors)...)) { return sprout::adaptors::apply_adaptors(sprout::forward(range), sprout::tuples::get(adaptors)...); } template SPROUT_CONSTEXPR auto apply_adaptors_tuple(Range&& range, AdaptorsTuple const& adaptors) -> decltype( sprout::adaptors::detail::apply_adaptors_tuple_impl( sprout::forward(range), adaptors, sprout::index_range<0, sprout::tuples::tuple_size::value>::make() ) ) { return sprout::adaptors::detail::apply_adaptors_tuple_impl( sprout::forward(range), adaptors, sprout::index_range<0, sprout::tuples::tuple_size::value>::make() ); } } // namespace detail // // pipe_holder // template class pipe_holder { public: typedef sprout::tuples::tuple adaptors_type; private: adaptors_type adaptors_; public: explicit SPROUT_CONSTEXPR pipe_holder(Adaptors const&... adaptors) : adaptors_(adaptors...) {} SPROUT_CONSTEXPR adaptors_type const& adaptors() const { return adaptors_; } template SPROUT_CONSTEXPR auto apply(Range&& range) const -> decltype(sprout::adaptors::detail::apply_adaptors_tuple(sprout::forward(range), std::declval().adaptors())) { return sprout::adaptors::detail::apply_adaptors_tuple(sprout::forward(range), adaptors()); } }; // // piped_forwarder // class piped_forwarder { public: template SPROUT_CONSTEXPR sprout::adaptors::pipe_holder operator()(Adaptors const&... adaptors) { return sprout::adaptors::pipe_holder(adaptors...); } }; // // piped // namespace { SPROUT_STATIC_CONSTEXPR sprout::adaptors::piped_forwarder piped{}; } // anonymous-namespace // // operator| // template inline SPROUT_CONSTEXPR auto operator|(Range&& lhs, sprout::adaptors::pipe_holder const& rhs) -> decltype(rhs.apply(sprout::lvalue_forward(lhs))) { return rhs.apply(sprout::lvalue_forward(lhs)); } } // namespace adaptors } // namespace sprout #endif // #ifndef SPROUT_RANGE_ADAPTOR_PIPED_HPP