Range of uncopyable elements

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Dec 8 13:46:26 PST 2016


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



More information about the Digitalmars-d-learn mailing list