Move upto from the std::ranges namespace into std::views
Use a more convincing example
Incorporate with the current iota wording in the standard
Since R1
Change the name views::upto to views::indices.
Use the is-integer-like exposition-only constraint rather than the std::integral (is-integer-like allows implementation-defined types and removes bool).
Abstract
We propose adding std::views::indices(n) to the C++ Standard Library as a range adaptor that generates a sequence of integers from 0 to n-1.
Motivation
Currently, iota(0, ranges::size(rng)) does not compile due to mismatched types (see point 1 in Background section). Then, users need to write a workaround like iota(range_size_t<decltype(rng)>{}, ranges::size(rng)), which is not straightforward and cumbersome. An example illustrating this issue is available at x8nWxqE9v:
C++23
std::vector rng(5,0);// auto res1 = views::iota(0, ranges::size(rng)); // does not compileauto res2 =iota(range_size_t<decltype(rng)>{}, ranges::size(rng));
std::print("{}", res2);// [0, 1, 2, 3, 4]
std::views::indices(n) eases this pattern by providing a straightforward method to generate integer sequences, improving readability and killing arcane code.
Implementation and Usage
namespace std::views {inlineconstexprauto indices =[]</*is-integer-like*/ I>(I n){return std::views::iota(I{}, n);};}
Two preceding proposals have provided fundation for std::views::indices(n):
P2214R2: A Plan for C++26 Ranges[1] highlights the issue with views::iota(0, r.size()) not compiling due to mismatched types. std::ranges::views::iota requires both arguments to be of the same type, or at least commonly comparable. This becomes problematic when comparing int (often 32-bit) with std::size_t (often 64-bit), which is usually wider on 64-bit systems. The same example from above Motivation section can be viewed at x8nWxqE9v.
std::vector rng(5,0);
auto res1 =iota(0, ranges::size(rng));// does not compile
P1894R0: Proposal of std::upto, std::indices and std::enumerate[2] proposed an implementation (see below) that our proposal refines. Our approach offers a more consistent interface, fitting seamlessly with existing standard library.
// std::upto implementation example
// P1894R0: Proposal of std::upto, std::indices and std::enumerate
namespace std {
template<typenameInt>
constexprautoupto(Int&& i)noexcept{
return std::ranges::iota_view{Int(),std::forward<Int>(i)};
}
}
Technical Decisions
Limiting to is-integer-like: is-integer-like allows implementation-defined types and removes bool.
Lambda-based Approach: Using a lambda is consistent with the established range adaptor patterns. Moreover, the use of constexpr allows for the evaluation to occur at compile-time.
Leveraging Existing iota_view Instead of Creating a New indices_view: Introducing indices_view would mean adding a component similar to what already exists, causing confusion and maintainability issues for users. By leveraging iota_view, we simplify the implementation and reuse of what the current C++ Standard Library offers. Additionally, any future optimizations to iota_view will automatically benefit std::views::indices. Therefore, by extending iota_view, std::views::indices becomes more maintainable, efficient, and simple.
The name views::indices denotes a customization point object ([customization.point.object]). Let E be an expression and let T be remove_cvref_t<decltype((E))>. If T does not model is-integer-like, views::indices(E) is ill-formed. Otherwise, the expression views::indices(E) is expression-equivalent to views::iota(T(), E).
Zhihao Yuan <zy@miator.net>
Add std::views::indices(n)
Revision History
upto
from thestd::ranges
namespace intostd::views
iota
wording in the standardviews::upto
toviews::indices
.is-integer-like
exposition-only constraint rather than thestd::integral
(is-integer-like
allows implementation-defined types and removes bool).Abstract
We propose adding
std::views::indices(n)
to the C++ Standard Library as a range adaptor that generates a sequence of integers from0
ton-1
.Motivation
Currently,
iota(0, ranges::size(rng))
does not compile due to mismatched types (see point 1 in Background section). Then, users need to write a workaround likeiota(range_size_t<decltype(rng)>{}, ranges::size(rng))
, which is not straightforward and cumbersome. An example illustrating this issue is available at x8nWxqE9v:C++23
P3060
std::views::indices(n)
eases this pattern by providing a straightforward method to generate integer sequences, improving readability and killing arcane code.Implementation and Usage
Usage:
Implementation: hsP97jKzv
Prior Art
Two preceding proposals have provided fundation for
std::views::indices(n)
:P2214R2: A Plan for C++26 Ranges[1] highlights the issue with
views::iota(0, r.size())
not compiling due to mismatched types.std::ranges::views::iota
requires both arguments to be of the same type, or at least commonly comparable. This becomes problematic when comparingint
(often 32-bit) withstd::size_t
(often 64-bit), which is usually wider on 64-bit systems. The same example from above Motivation section can be viewed at x8nWxqE9v.P1894R0: Proposal of std::upto, std::indices and std::enumerate[2] proposed an implementation (see below) that our proposal refines. Our approach offers a more consistent interface, fitting seamlessly with existing standard library.
Technical Decisions
Limiting to
is-integer-like
:is-integer-like
allows implementation-defined types and removes bool.Lambda-based Approach: Using a lambda is consistent with the established range adaptor patterns. Moreover, the use of
constexpr
allows for the evaluation to occur at compile-time.Leveraging Existing
iota_view
Instead of Creating a Newindices_view
: Introducingindices_view
would mean adding a component similar to what already exists, causing confusion and maintainability issues for users. By leveragingiota_view
, we simplify the implementation and reuse of what the current C++ Standard Library offers. Additionally, any future optimizations toiota_view
will automatically benefitstd::views::indices
. Therefore, by extendingiota_view
,std::views::indices
becomes more maintainable, efficient, and simple.Wording
Add a new parapgrah under [range.iota.overview]:
References
P2214R2 A Plan for C++26 Ranges. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2760r0.html ↩︎
P1894R0 Proposal of std::upto, std::indices and std::enumerate. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1894r0.pdf ↩︎