On Thursday, December 08, 2016 20:21:41 Jerry via Digitalmars-d-learn wrote: > Assuming that is wrong though, as you aren't copying an iterator > or range you are copying the actual value. What you are confusing > "auto h = r.front;" for is this: "auto rcopy = r;". The D code > "auto h = r.front" is not a cheap operation and the equivalent in > C++ is actually this: "auto h = *iterator;" and one should not > assume it is cheap, cause it isn't. Anyways your comparison with > C++ is off.
His comparison with C++ is off, because front isn't analogous to an iterator. It's analagous to dereferencing an iterator. However, at least as of C++98, non-copyable elements in a container were not allowed IIRC, so it would have been pretty rare to have a C++ iterator that returned a non-copyable value when you dereferenced it. Also, it pretty much _is_ assumed that auto h = r.front; is cheap, and there are plenty of cases where calling front multiple times for the same range would incur additional overhead, because front is calculated rather than simply returning a value (e.g. this is what happens with map). So, it could be a definite performance hit in general to start insisting that r.front be called without the value being assigned somewhere. Part of the problem here is that in some cases, it's more efficient to call front multiple times, whereas in others it's more efficient to call it once. But since most ranges do not have their front or back return by ref (and many cannot), it's going to be more efficient to call front only once for most ranges. Also, consider that the way that foreach works, it _has_ to be able to copy front unless it's used with ref - and since most ranges do not have a front that returns by ref, most ranges will not compile with a ref foreach variable, and generic code would fall completly flat on its face if it tried to use foreach with a range and made the foreach variable ref, whereas that's exactly what would be required for a range of non-copyable elements. Even if it were allowed, a range of non-copyable elements would not play nicely with the same code that a normal range would work with, resulting in a lot more conditional compilation from stuff like function overloading and static ifs in order to make the code work for both. So, allowing ranges of non-copyable types would tend to complicate code considerably - either that or a lot of template constraints would just do something like hasCopyableFront!R, making it so that ranges of non-copyable elements still really didn't work. Yes, not allowing copyable elements for ranges is a problem. But allowing them would also be a big problem. What we should ultimately do about it, I don't know, but I think that it's pretty clear that the majority of code would be better off if non-copyable elements for ranges were not allowed. And it _is_ possible to work around the problem by doing as H.S. Teoh suggested and using ranges of pointers. - Jonathan M Davis