/// \file // Range v3 library // // Copyright Mitsutaka Takeda 2018-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 RANGE_V3_VIEW_EXCLUSIVE_SCAN_HPP #define RANGE_V3_VIEW_EXCLUSIVE_SCAN_HPP #include #include #include #include #include #include #include namespace ranges { // clang-format off CPP_def ( template(typename Rng, typename T, typename Fun) concept exclusive_scan_constraints, viewable_range && input_range && copy_constructible && invocable> && assignable_from>> ); // clang-format on /// \addtogroup group-views /// @{ template struct exclusive_scan_view : view_adaptor, Rng> { private: friend range_access; CPP_assert(exclusive_scan_constraints); semiregular_box_t init_; semiregular_box_t fun_; using single_pass = meta::bool_>>; using use_sentinel_t = meta::bool_ || single_pass{}>; template struct adaptor : adaptor_base { private: friend struct adaptor; using exclusive_scan_view_t = meta::const_if_c; using CRng = meta::const_if_c; semiregular_box_t sum_; exclusive_scan_view_t * rng_; // clang-format off auto CPP_auto_fun(move_or_copy_init)(std::false_type) ( return (rng_->init_) ) // If the base range is single-pass, we can move the init value. auto CPP_auto_fun(move_or_copy_init)(std::true_type) ( return std::move(rng_->init_) ) // clang-format on public : using single_pass = exclusive_scan_view::single_pass; adaptor() = default; adaptor(exclusive_scan_view_t * rng) : rng_(rng) {} CPP_template(bool Other)( // requires IsConst && (!Other)) adaptor(adaptor that) : rng_(that.rng_) {} iterator_t begin(exclusive_scan_view_t &) { sum_ = move_or_copy_init(single_pass{}); return ranges::begin(rng_->base()); } T read(iterator_t const &) const { return sum_; } void next(iterator_t & it) { RANGES_EXPECT(it != ranges::end(rng_->base())); sum_ = invoke(rng_->fun_, static_cast(std::move(sum_)), *it); ++it; } void prev() = delete; }; adaptor begin_adaptor() { return {this}; } meta::if_> end_adaptor() { return {this}; } CPP_member auto begin_adaptor() const -> CPP_ret(adaptor)( // requires exclusive_scan_constraints) { return {this}; } CPP_member auto end_adaptor() const -> CPP_ret(meta::if_>)( // requires exclusive_scan_constraints) { return {this}; } public: exclusive_scan_view() = default; constexpr exclusive_scan_view(Rng rng, T init, Fun fun) : exclusive_scan_view::view_adaptor{std::move(rng)} , init_(std::move(init)) , fun_(std::move(fun)) {} CPP_member auto CPP_fun(size)()(const requires sized_range) { return ranges::size(this->base()); } CPP_member auto CPP_fun(size)()(requires sized_range) { return ranges::size(this->base()); } }; #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 CPP_template(typename Rng, typename T, typename Fun)(requires copy_constructible && copy_constructible) exclusive_scan_view(Rng &&, T, Fun) ->exclusive_scan_view, T, Fun>; #endif namespace views { struct exclusive_scan_fn { private: friend view_access; template static constexpr auto bind(exclusive_scan_fn exclusive_scan, T init, Fun fun = {}) { return make_pipeable( bind_back(exclusive_scan, std::move(init), std::move(fun))); } public: template constexpr auto operator()(Rng && rng, T init, Fun fun = Fun{}) const -> CPP_ret(exclusive_scan_view, T, Fun>)( // requires exclusive_scan_constraints) { return {all(static_cast(rng)), std::move(init), std::move(fun)}; } }; /// \relates exclusive_scan_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view, exclusive_scan) } // namespace views /// @} } // namespace ranges #endif // RANGE_V3_VIEW_EXCLUSIVE_SCAN_HPP