| Doc. no.: | P3060R3 |
| Date: | 2025-6-18 |
| Audience: | LWG |
| Reply-to: |
Weile Wei <weilewei09@gmail.com>
Zhihao Yuan <zy@miator.net> |
Add std::views::indices(n)
Revision History
- Since R0
-
- 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).
- Since R2
-
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:
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 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.
-
P1894R0: Proposal of std::upto, std::indices and std::enumerate 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 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.
Wording
Add a new paragraph under [range.iota.overview]:
26.6.4.1 Overview [range.iota.overview]
The name views::indices denotes a customization point object ([customization.point.object]). Given subexpression E, let T be remove_cvref_t<decltype((E))>. views::indices(E) is expression-equivalent to views::iota(T(0), E) if T models is-integer-like, and ill-formed otherwise.
Modify [ranges.syn] as follows:
// [range.iota], iota view
[...]
namespace views { inline constexpr unspecified iota = unspecified; }
inline constexpr unspecified iota = unspecified;
inline constexpr unspecified indices = unspecified;
}
Feature test macro
Add __cpp_lib_ranges_indices to [version.syn]:
#define __cpp_lib_ranges_indices 202XXXL // also in <ranges>
References
Zhihao Yuan <zy@miator.net>
Add std::views::indices(n)
Revision History
uptofrom thestd::rangesnamespace intostd::viewsiotawording in the standardviews::uptotoviews::indices.is-integer-likeexposition-only constraint rather than thestd::integral(is-integer-likeallows 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 from0ton-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::iotarequires 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-likeallows implementation-defined types and removes bool.Lambda-based Approach: Using a lambda is consistent with the established range adaptor patterns. Moreover, the use of
constexprallows for the evaluation to occur at compile-time.Leveraging Existing
iota_viewInstead of Creating a Newindices_view: Introducingindices_viewwould 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_viewwill automatically benefitstd::views::indices. Therefore, by extendingiota_view,std::views::indicesbecomes more maintainable, efficient, and simple.Wording
Add a new paragraph under [range.iota.overview]:
Modify [ranges.syn] as follows:
Feature test macro
Add
__cpp_lib_ranges_indicesto [version.syn]: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 ↩︎