Created on 2025-10-02.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N5014.
Modify [range.join.view] as indicated:
[Drafting note: The proposed wording follows the
tiny-range's way to check if `R::size()` is a constant expression instead of further checking `ranges::size(r)` for simplicity.]
namespace std::ranges {
template<auto> struct require-constant; // exposition only
template<class R>
concept static-sized-range = // exposition only
sized_range<R> &&
requires { typename require-constant<remove_reference_t<R>::size()>; };
template<input_range V>
requires view<V> && input_range<range_reference_t<V>>>
class join_view : public view_interface<join_view<V>> {
[…]
public:
[…]
constexpr auto size()
requires sized_range<V> && static-sized-range<InnerRng> {
using CT = common_type_t<range_size_t<V>, range_size_t<InnerRng>>;
return CT(ranges::size(base_)) * CT(remove_reference_t<InnerRng>::size());
}
constexpr auto size() const
requires sized_range<const V> &&
static-sized-range<range_reference_t<const V>> {
using InnerConstRng = range_reference_t<const V>;
using CT = common_type_t<range_size_t<V>, range_size_t<InnerConstRng>>;
return CT(ranges::size(base_)) * CT(remove_reference_t<InnerConstRng>::size());
}
};
[…]
}
Modify [range.join.with.view] as indicated:
namespace std::ranges {
[…]
template<input_range V, forward_range Pattern>
requires view<V> && input_range<range_reference_t<V>>
&& view<Pattern>
&& concatable<range_reference_t<V>, Pattern>
class join_with_view : public view_interface<join_with_view<V, Pattern>> {
[…]
public:
[…]
constexpr auto size()
requires sized_range<V> && sized_range<Pattern> &&
static-sized-range<InnerRng> {
using CT = common_type_t<
range_size_t<V>, range_size_t<InnerRng>, range_size_t<Pattern>>;
const auto base_size = ranges::size(base_);
if (base_size == 0)
return CT(0);
return CT(base_size) * CT(remove_reference_t<InnerRng>::size()) +
CT(base_size - 1) * CT(ranges::size(pattern_));
}
constexpr auto size() const
requires sized_range<const V> && sized_range<const Pattern> &&
static-sized-range<range_reference_t<const V>> {
using InnerConstRng = range_reference_t<const V>;
using CT = common_type_t<
range_size_t<const V>, range_size_t<InnerConstRng>, range_size_t<const Pattern>>;
const auto base_size = ranges::size(base_);
if (base_size == 0)
return CT(0);
return CT(base_size) * CT(remove_reference_t<InnerConstRng>::size()) +
CT(base_size - 1) * CT(ranges::size(pattern_));
}
};
[…]
}
Modify [range.lazy.split.view] as indicated:
namespace std::ranges {
template<auto> struct require-constant; // exposition only
template<class R>
concept tiny-range = // exposition only
static-sized-range<R>sized_range<R> &&
requires { typename require-constant<remove_reference_t<R>::size()>; } &&
(remove_reference_t<R>::size() <= 1);
[…]
}
[ 2025-10-23; Reflector poll; Status changed: New → LEWG and P3. ]
Introducting statically sized ranges and handling them in views, should be handle as a paper.
The proposed change is also relevant to fixed-size span.
Consider:
Collecting a `simd::vec` into a `vector` for output is a common use case. P3480R6 makes `simd::vec` a range so we can simply flatten it with `views::join` (original example from the paper):std::vector<std::simd::vec<float>> data; auto range_of_float = data | std::views::join;
In this case, it makes sense for `join_view` to be `sized_range` because `simd::vec::size()` is a constant expression that can be multiplied by the original `vector` size to get the result size of the `join_view`.
In<ranges>, we use the tiny-range concept
to consider types that can obtain static sizes specifically, and `simd::vec`
seems to be a good fit.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-10-23 09:34:52 | admin | set | messages: + msg15372 |
| 2025-10-23 09:34:52 | admin | set | status: new -> lewg |
| 2025-10-04 13:39:45 | admin | set | messages: + msg15120 |
| 2025-10-02 00:00:00 | admin | create | |