Range of uncopyable elements
H. S. Teoh via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Dec 8 09:29:42 PST 2016
On Thu, Dec 08, 2016 at 05:22:25PM +0000, Jerry via Digitalmars-d-learn wrote:
> On Thursday, 8 December 2016 at 16:48:07 UTC, H. S. Teoh wrote:
> > On Thu, Dec 08, 2016 at 04:35:02PM +0000, Jerry via Digitalmars-d-learn
> > wrote:
> > > The problem is with how isInputRange is defined, requires that
> > > front be copyable.
> > >
> > > auto h = r.front; // can get the front of the range
> > >
> > > https://github.com/dlang/phobos/blob/v2.072.1/std/range/primitives.d#L168
> > >
> > > It doesn't take into consideration that front exists and that it's
> > > a reference to a struct that can't be copied. There was a
> > > discussion a while back to change it but it seems nothing came of
> > > it.
> >
> > A possible workaround, which is somewhat ugly but should work, is to
> > have the range return pointers to the elements instead of the
> > elements themselves. For the most part, this should be mostly
> > transparent because the . operator automatically dereferences.
> >
> >
> > T
>
> It's not something that you should have to workaround, isInputRange is not
> defined properly and should be fixed. You end up complicating your code for
> no reason other than isInputRange is poorly defined.
The problem is that most range algorithms won't work if `auto h =
r.front;` doesn't compile. Random chunks of std.algorithm won't work
for such a range.
One may argue, of course, that std.algorithm ought to be fixed... but
the root of the problem really is a conceptual one. The definition of a
range was made as an extension of a C++ iterator, which is basically a
wrapped pointer. So `auto h = r.front;` is assumed to be a cheap copy of
a *reference* to the underlying data, rather than copying the data
itself. This is why most of std.algorithm is written the way it is, and
why isInputRange is defined the way it is. A range of non-copyable
elements in this sense is a poor fit for the range concept; a better fit
would be a range of references to an underlying container of
non-copyable elements. Hence my suggestion of using pointers.
(In any case, conflating a range with a container is usually a red flag
that there's a conceptual mismatch somewhere. Unfortunately built-in
arrays aren't helping by hiding the fact that the container is actually
GC-managed memory, which isn't directly visible to the user, thus
perpetuating the misconception that range == container.)
T
--
What did the alien say to Schubert? "Take me to your lieder."
More information about the Digitalmars-d-learn
mailing list