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