Created on 2022-05-17.00:00:00 last changed 33 months ago
[ 2023-03-22 Resolved by the adoption of P2770R0 in Issaquah. Status changed: New → Resolved. ]
[ 2022-06-21; Reflector poll ]
Set priority to 3 after reflector poll.
This wording is relative to N4910.
Modify [range.join.view], class template join_view synopsis, as indicated:
namespace std::ranges {
[…]
template<input_range V>
requires view<V> && input_range<range_reference_t<V>>
class join_view : public view_interface<join_view<V>> {
private:
[…]
public:
[…]
constexpr auto begin() {
[…]
}
constexpr auto begin() const
requires input_range<const V> &&
input_range<range_reference_t<const V>> &&
is_reference_v<range_reference_t<const V>>
{ return iterator<true>{*this, ranges::begin(base_)}; }
constexpr auto end() {
[…]
}
constexpr auto end() const
requires input_range<const V> &&
input_range<range_reference_t<const V>> &&
is_reference_v<range_reference_t<const V>> {
if constexpr (forward_range<const V> &&
forward_range<range_reference_t<const V>> &&
common_range<const V> &&
common_range<range_reference_t<const V>>)
return iterator<true>{*this, ranges::end(base_)};
else
return sentinel<true>{*this};
}
};
[…]
}
Modify [range.join.with.view], class template join_with_view synopsis, as indicated:
namespace std::ranges {
[…]
template<input_range V, forward_range Pattern>
requires view<V> && input_range<range_reference_t<V>>
&& view<Pattern>
&& compatible-joinable-ranges<range_reference_t<V>, Pattern>
class join_with_view : public view_interface<join_with_view<V, Pattern>> {
private:
[…]
public:
[…]
constexpr auto begin() {
[…]
}
constexpr auto begin() const
requires input_range<const V> &&
forward_range<const Pattern> &&
input_range<range_reference_t<const V>> &&
is_reference_v<range_reference_t<const V>> {
return iterator<true>{*this, ranges::begin(base_)};
}
constexpr auto end() {
[…]
}
constexpr auto end() const
requires input_range<const V> && forward_range<const Pattern> &&
input_range<range_reference_t<const V>> &&
is_reference_v<range_reference_t<const V>> {
using InnerConstRng = range_reference_t<const V>;
if constexpr (forward_range<const V> && forward_range<InnerConstRng> &&
common_range<const V> && common_range<InnerConstRng>)
return iterator<true>{*this, ranges::end(base_)};
else
return sentinel<true>{*this};
}
};
[…]
}
This is a follow-up of LWG 3599.
Currently, the const version of join_view::begin has the following constraints
constexpr auto begin() const
requires input_range<const V> &&
is_reference_v<range_reference_t<const V>>
{ return iterator<true>{*this, ranges::begin(base_)}; }
which only requires InnerRng to be a reference type, but in some cases, InnerRng may not be a range. Consider
#include <ranges>
int main() {
auto r = std::views::iota(0, 5)
| std::views::split(1);
auto s = std::views::single(r);
auto j = s | std::views::join;
auto f = j.front();
}
The reference type of single_view is const split_view&, which only has the non-const version of begin, which will cause view_interface's const front to be incorrectly instantiated, making r.front() unnecessarily ill-formed.
We should add this check for join_view's const begin, as well as join_with_view.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2023-03-23 11:42:08 | admin | set | status: new -> resolved |
| 2022-06-21 11:46:11 | admin | set | messages: + msg12511 |
| 2022-05-21 11:42:57 | admin | set | messages: + msg12472 |
| 2022-05-17 00:00:00 | admin | create | |