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."