On Tuesday, 5 May 2015 at 02:47:03 UTC, bitwise wrote:
On Mon, 04 May 2015 00:16:03 -0400, Jonathan M Davis via
Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
D will move the argument if it can rather than copying it
(e.g. if a
temporary is being passed in), which reduces the need for
worrying about
copying like you tend to have to do in C++98, and I think that
a lot of D
code just doesn't worry about the cost of copying structs.
How exactly would you move a struct? Just a memcpy without the
postblit?
Because D has postblit constructors rather than copy
constructors, copying is done by blitting the entire struct and
then calling the postlblit constructor afterwards, so unless the
postlbit constructor is @disabled, a struct is moveable simply by
blitting it and not calling the postblit constructor afterwards.
And the compiler can choose to do a move whenever a copy is
unnecessary (e.g. return value optimization or when a temporary
is passed to a
However, if you have a large object that you know is going to
be
expensive to copy, you're either going to have to use const ref
(and thus probably duplicate the function to allow rvalues), or
you're going to need to make it a reference type rather than
having all of its data live on the stack (either by making
it so that the struct contains a pointer to its data or by
making it a
class).
In general, if you're dealing with a type that is going to be
expensive to copy, I'd advise making it a reference type over
relying on
const ref simply because it's less error-prone that way. It's
trivial to
forget to use ref on a parameter, and generic code won't use
it, so it'll
generally work better to just make it a reference type.
- Jonathan M Davis
Something like a Matrix4x4 lives in an awkward place between a
class and a struct. Because of the fact that a graphics engine
may have to deal with thousands of them per frame, both copying
them at function calls, and allocating/collecting thousands of
them per frame, are both unacceptable.
I was reading up(DIP36, pull requests, forum) and it seems like
auto ref was supposed to do something like this. Is there a
reason you didn't mention it?
You could use auto ref, but then you'd have to templatize the
function, since it only works with templated functions, and if
you have multiple auto ref parameters, then you'll get a
combinatorial explosion of template instantations as you call the
function with different combinations of lvalues and rvalues. It's
basically like declaring each of the combinations of the function
with ref and non-ref parameters, but you don't have to declare
them all, and it doesn't work with virtual functions. I didn't
mention auto ref mostly just to be simple.
But because of that combinatorial explosion (be they declared
implicitly via auto ref or manually) is a good reason IMHO to
just not worry about this problem in most cases. It's just too
tedious to duplicate all functions like that, and using templates
isn't always acceptable.
In theory, auto ref could work for non-templated functions by
making it so that underneath the hood as ref except that any time
you passed it an rvalue, it implicitly defined an lvalue for you
to pass to the function, but that doesn't match what happens with
auto ref with non-templated functions, and changing the behavior
for templated functions would be unacceptable, because it would
reduce our ability to forward parameters without changing their
type, so we'd end up with auto ref doing different things on
templated and non-templated functions, which is potentially
confusing. And that solution has simply never been agreed upon. I
have no idea if it ever will be.
Why not just add "rvref" to D?
Because we have too many attributes already. It's actually kind
of astonishing that we're getting return ref, because Andrei was
adamant that we not add any more parameter attributes, because we
simply have too many already. I think that the only reasons that
return ref is making it in is because of how it solves a real
need and how simple it is, whereas Andrei is not at all convinced
that having anything like C++'s const& in D is needed. And while
it might be nice, for the most part, we _are_ able to mostly
write code without worrying about it.
- Jonathan M Davis