D's equivalent to C++'s std::move?

Matt Elkins via Digitalmars-d digitalmars-d at puremagic.com
Wed Feb 3 18:01:51 PST 2016


On Thursday, 4 February 2016 at 01:26:55 UTC, Andrei Alexandrescu 
wrote:
> On 02/03/2016 07:48 PM, Matt Elkins wrote:
>> This [apparent] lack of clean move semantics
>
> I very much wish there was a quick summary. I figure you've 
> seen std.algorithm.move. What's missing? -- Andrei

Apologies, should have summarized. The issue I've been focused on 
has been emulating C++'s std::unique_ptr for the purposes of 
handling system resources which need explicit cleanup and which 
are not copyable (or for which I want to disallow copying for 
whatever reason). I want to still be able to move around my 
handles to these resources, so long as the single-owner aspect is 
maintained, and I want the wrapper to have minimal overhead (so 
for example std.typecons.Unique is out, since it appears to 
require the heap one way or another); in essence, I want 
std::unique_ptr. It is quite possible that this is doable, but if 
so the solution eludes me. Here is what I have so far:

[code]
import std.algorithm;

struct ResourceHandle(T, alias Deleter, T Default = T.init)
{
     // Constructors/Destructor
     this(T handle) {m_handle = handle;}
     @disable this(this);
     ~this() {Deleter(m_handle);}

     // Operators
     @disable void opAssign(ref ResourceHandle lvalue);
     ref ResourceHandle opAssign(ResourceHandle rvalue) 
{swap(m_handle, rvalue.m_handle); return this;}

     // Methods
     @property inout(T) handle() inout {return m_handle;}
     @property T handle(T handle) {Deleter(m_handle); m_handle = 
handle; return m_handle;}
     T release() {T result = m_handle; m_handle = Default; return 
result;}

     private:
         T m_handle = Default;
}
[/code]

This seems to cover most of my bases, but I still can't do things 
like this:

[code]
unittest
{
     alias RH = ResourceHandle!(uint, (uint) {});
     RH[] handles;
     handles ~= RH(5); // Compile error: ResourceHandle is not 
copyable because it is annotated with @disable
}
[/code]

One person on the forums suggested that this might be a compiler 
bug (and referred me to a maybe-related bug report from 2011), 
but it also might not. This seems to have similar practical 
functionality to std::auto_ptr; works reasonably well for passing 
around individual instances, but gets iffy when you want to put 
it into a container. Incidentally, I -am- able to do this:

[code]
unittest
{
     alias RH = ResourceHandle!(uint, (uint) {});

     RH[] handles;
     ++handles.length;
     handles[$ - 1] = RH(5);
}
[/code]

This has become my effective workaround, but it isn't terribly 
clean and may not scale to other kinds of data structures (or it 
may, haven't thought it through). Of course, I'm a D newbie and 
could well just not be seeing the right way to define 
ResourceHandle.

Sorry for all the C++ allusions to explain my intent. Then again, 
I'm not terribly worried that the author of MC++D won't follow 
them :).


More information about the Digitalmars-d mailing list