Move semantics for D
Jonathan M Davis
jmdavisProg at gmx.com
Fri Jul 13 02:16:11 PDT 2012
On Friday, July 13, 2012 11:09:04 Benjamin Thaut wrote:
> Am 13.07.2012 10:59, schrieb Christophe Travert:
> > Benjamin Thaut , dans le message (digitalmars.D:172207), a écrit :
> >> Move semantics in C++0x are quite nice for optimization purposes.
> >> Thinking about it, it should be fairly easy to implement move semantics
> >> in D as structs don't have identity. Therefor a move constructor would
> >> not be required. You can already move value types for example within an
> >> array just by plain moving the data of the value around. With a little
> >> new keyword 'mov' or 'move' it would also be possible to move value
> >> types into and out of functions, something like this:
> >>
> >> mov Range findNext(mov Range r)
> >> {
> >>
> >> //do stuff here
> >>
> >> }
> >>
> >> With something like this it would not be neccessary to copy the range
> >> twice during the call of this function, the compiler could just plain
> >> copy the data and reinitialize the origin in case of the argument.
> >> In case of the return value to only copying would be neccessary as the
> >> data goes out of scope anyway.
> >
> > If Range is a Rvalue, it will be moved, not copied.
> > It it's a Lvalue, your operation is dangerous, and does not bring you
> > much more than using ref (it may be faster to copy the range than to
> > take the reference, but that's an optimiser issue).
> >
> > auto ref seems to be the solution.
> >
> >> I for example have a range that iterates over a octree and thus needs to
> >> internally track which nodes it already visited and which ones are still
> >> left. This is done with a stack container. That needs to be copied
> >> everytime the range is copied, which causes quite some overhead.
> >
> > I would share the tracking data between several instance of the range,
> > making bitwise copy suitable. Tracking data would be duplicated only on
> > call to save or opSlice(). You'd hit the issue of foreach not calling
> > save when it should, but opSlice would solve this, and you could still
> > overload opApply if you want to be sure.
>
> I couldn't find anything in the documentation about foreach calling save
> or opSlice(). So I assume foreach calls opSlice if aviable?
If you have
foreach(e; obj)
{
...
}
and obj is a range, then it becomes
for(auto __range = obj; !__range.empty; __range.popFront())
{
auto e = __range.front;
...
}
If obj is not a range, but it does declare opSlice, then it's sliced, so you
get something like
for(auto __range = obj[]; !__range.empty; __range.popFront())
{
auto e = __range.front;
...
}
There's also opApply to consider though, and it probably gets precedence over
opSlice if a type defines both. I don't know exactly how all of that's laid out
right now though. However, there's a recent thread discussing it ("opApply not
called for foeach(container)"), so you can read that, and I think that they
give better details on precedence. I haven't read it in great detail though,
so I don't know the details other than the fact that it sounds like the
precedence rules for foreach probably neet do be ironed out better.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list