This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
join_view
should be sized_range
when applied to ranges of simd::vec
Section: 25.7.14.2 [range.join.view], 25.7.15.2 [range.join.with.view], 25.7.16.2 [range.lazy.split.view] Status: New Submitter: Hewill Kang Opened: 2025-10-02 Last modified: 2025-10-04
Priority: Not Prioritized
View other active issues in [range.join.view].
View all other issues in [range.join.view].
View all issues with New status.
Discussion:
Consider:
Collecting asimd::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
.
<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.
Proposed resolution:
This wording is relative to N5014.
Modify 25.7.14.2 [range.join.view] as indicated:
[Drafting note: The proposed wording follows the
tiny-range
's way to check ifR::size()
is a constant expression instead of further checkingranges::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 25.7.15.2 [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 25.7.16.2 [range.lazy.split.view] as indicated:
namespace std::ranges {template<auto> struct require-constant; // exposition onlytemplate<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); […] }