Created on 2023-01-06.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to N4917.
Modify [range.chunk.inner.iter] as indicated:
[…]namespace std::ranges { template<view V> requires input_range<V> class chunk_view<V>::inner-iterator { chunk_view* parent_; // exposition only constexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition only public: […] friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_))); friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires indirectly_swappable<iterator_t<V>>; }; }friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));-?- Effects: Equivalent to: return ranges::iter_move(*i.parent_->current_);
friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires indirectly_swappable<iterator_t<V>>;-?- Effects: Equivalent to: ranges::iter_swap(*x.parent_->current_, *y.parent_->current_).
[ 2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP. ]
[ 2023-02-01; Reflector poll ]
Set status to Tentatively Ready after five votes in favour during reflector poll.
For the input version of chunk_view, its inner-iterator::operator*() simply dereferences the underlying input iterator. However, there are no customized iter_move and iter_swap overloads for the inner-iterator, which prevents customized behavior when applying views::chunk to a range whose iterator type is a proxy iterator, for example:
#include <algorithm>
#include <cassert>
#include <ranges>
#include <sstream>
#include <vector>
int main() {
auto ints = std::istringstream{"0 1 2 3 4"};
std::vector<std::string> vs{"the", "quick", "brown", "fox"};
auto r = std::views::zip(vs, std::views::istream<int>(ints))
| std::views::chunk(2)
| std::views::join;
std::vector<std::tuple<std::string, int>> res;
std::ranges::copy(std::move_iterator(r.begin()), std::move_sentinel(r.end()),
std::back_inserter(res));
assert(vs.front().empty()); // assertion failed
}
zip iterator has a customized iter_move behavior, but since there is no iter_move specialization for inner-iterator, when we try to move elements in chunk_view, move_iterator will fallback to use the default implementation of iter_move, making strings not moved as expected from the original vector but copied instead.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2023-02-13 10:17:57 | admin | set | messages: + msg13371 |
2023-02-13 10:17:57 | admin | set | status: voting -> wp |
2023-02-06 15:33:48 | admin | set | status: ready -> voting |
2023-02-01 20:36:59 | admin | set | messages: + msg13245 |
2023-02-01 20:36:59 | admin | set | status: new -> ready |
2023-01-06 16:24:01 | admin | set | messages: + msg13189 |
2023-01-06 00:00:00 | admin | create |