On Sunday, 21 January 2024 at 05:00:31 UTC, Jonathan M Davis wrote:
>Ultimately, I'm inclined to argue that we should give basic input ranges a new API - not just because it would allow them to use reference counting, but also because the current input range API tends to force basic input ranges to cache the value of front (which if anything, encourages basic input ranges to be pseudo-reference types and could result in an extra layer of indirection in some cases if they're forced to be reference types). It would be annoying in some cases to require that different functions be used for basic input ranges and forward ranges (though overloading could obviously be used to avoid needing different names), but it's already often the case that code isn't really designed to work with both, and overloading on the category of range being used is already fairly common, since different range capabilities allow for different implementations. So, given that it would prevent whole classes of copying bugs as well as potentially remove the requirement to cache front for basic input ranges, I think that a separate API for basic input ranges is warranted. What I would propose for that would be a single function
auto next();
where next returns a nullable type where the value returned is the next element in the range, with a null value being returned if the range is empty. The return type would then need to emulate a pointer - specifically, when casting it to bool, it would be true if it's non-null and false if it's null, and dereferencing it would give you the actual value if it's non-null (with it being undefined behavior if you dereference null). So, a basic input range of ints might define next as
int* next();
While I agree with most of what you wrote, there is one very big problem with this. Namely, current input ranges are suddenly considered to be forward ranges. Changing the semantics of what it means to only define front
, popFront
, and empty
changes the semantics of existing code.
And this is not something you can solve with some kind of versioning. The only way I can think of is to alter the name of one or more primitives to prevent accidental usage.
-Steve