Should the "front" range primitive be "const" ?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Mar 19 00:50:06 UTC 2018


On Monday, March 19, 2018 00:14:11 Drone1h via Digitalmars-d-learn wrote:
> I am not sure whether I can make it work with "inout" instead of
> "const". Perhaps I am missing something.
...
> May I ask that you confirm that this is what you suggested ?
> Thank you.

Marking a empty or front with inout has most of the problems that const has.
The difference is that if the range is mutable, then the return value will
be treated as mutable. The internals of the function, however, must still
work with const or inout, and that's not true for most ranges. It can work
just fine to mark empty or front as inout or const if you're in full control
of the element types and aren't wrapping other ranges, but as soon as you
start wrapping other ranges, you pretty much must give up on inout and
const, because most ranges won't work with them - even to just call empty or
front. And in many cases, they can't be made to work with const or inout,
because that often causes serious problems with the return type. The range
API simply does not include const or inout, so you can't assume that any
range will compile with them, meaning that ranges that wrap other ranges can
only use const or inout when they're intended to wrap a very specific set of
ranges that do work with const or inout. Ranges that generically wrap other
ranges cannot use const or inout, or they will not compile with many (most?)
ranges.

> > [...] const ranges are utterly useless, because they can't be
> > mutated and thus can't be iterated. [...]
>
> I am considering a function that takes as parameter a (reference
> to) const range. It should be able to check whether the range is
> "empty" and, if not empty, it should be able to access the
> "front" element.
>
> Now the caller of that function can rest assured that the
> function is not going to modify the range by "popFront".
>
> The function might be more useful than a function that just takes
> as parameter a value (the result of "front") because it may be
> called with an empty range and it can detect that. This is
> similar to getting as parameter a (possibly null) pointer to a
> value instead of getting as parameter a value.
>
> Therefore, it seems to me that a const range might be useful.
>
> If you have already considered this and have actually seen
> one-step ahead of me, may I ask that you confirm, please ?

Most ranges do not work with const in any way shape or form. _Some_ will
work if all you're doing is looking at is empty or front. But if all you're
doing is looking at the front, in general, why pass a range? Just call front
and pass it, and then the function will work with more than just ranges.
Yes, if you want a function that does something like

auto frontOrInit(R)(R range)
{
    return range.empty ? ElementType!R.init : range.front;
}

then you can make the range const, but in general, a function is either
going to be iterating over the range (so the range can't be const), or what
the function is doing really has nothing to do with ranges and would be far
more flexible if it just took the range's element type. Functions like
frontOrInit where it would make sense to only call front or empty on a range
are rare. And honestly, making a function like frontOrInit accept the range
by const doesn't buy you much if a range's front and empty are const, and it
makes the function useless with most ranges, because most ranges don't - and
many can't - mark front or empty as const.

Honestly, I think that you will be far better off if you just don't try and
use const or inout with ranges. You can make it work in very restricted
circumstances, but you will constantly be fighting problems where code does
not compile. I'd suggest that you read this:

http://jmdavisprog.com/articles/why-const-sucks.html

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list