On Tuesday, January 30, 2018 01:05:54 Drone1h via Digitalmars-d-learn wrote:
> Hello all,
>
>
>
> I am trying to implement a ("struct template" ? what is the
> correct word ?) range that just forwards its primitives ("empty",
> "front", "popFront") to another range, possibly with some very
> limited filtering/alteration, as std.range.Take (just to learn).
>
> Initially, the "front" member function (property) used to be
> declared "const", but that was not accepted when the underlying
> range (denoted "R" in the code below) was std.stdio.File.ByChunk
> ("Error: mutable method std.stdio.File.ByChunk.front is not
> callable using a const object").
>
> Is there any value in having the "front" range primitive declared
> to be a "const"  member function ?
>
> And if so, is the following implementation okay ? Could it be
> further simplified ?
>
>      struct Taker (R)
>      {
>          private R _r;
>
>          ...
>
>          static if (functionAttributes ! (R.front) &
> FunctionAttribute.const_)
>              public @property auto front () const { return
> _r.front; }
>          else
>              public @property auto front ()       { return
> _r.front; }
>
>          ...
>      }
>
>
>
> Thank you respectfully !
> Drone1h

If you want to put an attribute on it, inout is better, because then it will
work with any constness, but in general, I'd suggest just avoiding the use
of const or immutable altogether when dealing with ranges. front can return
a const element, and that will happen if you use auto and whatever you're
wrapping is const, but const ranges are utterly useless, because they can't
be mutated and thus can't be iterated. As such, almost no code is ever going
to have a range that is anything but mutable, which means that having front
be anything but mutable is generally pointless.

The design of ranges makes them fundamentally incompatible with const. We'd
had to have gone with the head/tail model where you get an entirely new
object every time you pop elements off if we wanted const or immutable to
work. The fact that popFront pretty much outright kills const.

If tail-const slicing were a thing for ranges, then we'd get something
similar to tail/cdr out of the deal, and const ranges could be made to work,
but it's a royal pain to do tail-const with user-defined types (especially
templated types), and slicing an entire range like that isn't actually part
of the range API. hasSlicing requires slicing indices but not the entire
range. Slicing without indices operation is used on containers to get ranges
but isn't used for ranges themselves.

So, as it stands at least, I'd suggest that you simply not bother using
const with ranges.

- Jonathan M Davis

Reply via email to