www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - UniquePtr in D

reply Benjamin Thaut <code benjamin-thaut.de> writes:
When working with C-libraries in D I often wish for a equivalent of the 
C++11 unique_ptr. Unfortunately this is not possible in D. Consider the 
following source code:

http://dpaste.dzfl.pl/6e71c815

Is error 1 a bug? Because there should cleary not be any copy at this point.

Should we implement moving of u so that error 2 goes away? The compiler 
could move u into the function and move back out afterwards, but that 
would mean that the contents of u would be invalid for the duration of 
the function call (unsafe?)

Kind Regards
Benjamin Thaut
Dec 22 2013
next sibling parent reply "Kelet" <kelethunter gmail.com> writes:
On Sunday, 22 December 2013 at 13:19:48 UTC, Benjamin Thaut wrote:
 When working with C-libraries in D I often wish for a 
 equivalent of the C++11 unique_ptr. Unfortunately this is not 
 possible in D. Consider the following source code:

 http://dpaste.dzfl.pl/6e71c815

 Is error 1 a bug? Because there should cleary not be any copy 
 at this point.

 Should we implement moving of u so that error 2 goes away? The 
 compiler could move u into the function and move back out 
 afterwards, but that would mean that the contents of u would be 
 invalid for the duration of the function call (unsafe?)

 Kind Regards
 Benjamin Thaut
Is std.typecons.Unique[1] not the equivalent of unique_ptr? Regards, Kelet
Dec 22 2013
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 22.12.2013 14:24, schrieb Kelet:
 On Sunday, 22 December 2013 at 13:19:48 UTC, Benjamin Thaut wrote:
 When working with C-libraries in D I often wish for a equivalent of
 the C++11 unique_ptr. Unfortunately this is not possible in D.
 Consider the following source code:

 http://dpaste.dzfl.pl/6e71c815

 Is error 1 a bug? Because there should cleary not be any copy at this
 point.

 Should we implement moving of u so that error 2 goes away? The
 compiler could move u into the function and move back out afterwards,
 but that would mean that the contents of u would be invalid for the
 duration of the function call (unsafe?)

 Kind Regards
 Benjamin Thaut
Is std.typecons.Unique[1] not the equivalent of unique_ptr? Regards, Kelet
Well yes, but I'm more interrested in moving around the ownership between functions, which works in c++11 because of the move semantics they implemented. This doesn't work in D for the shown reasons.
Dec 22 2013
next sibling parent Benjamin Thaut <code benjamin-thaut.de> writes:
I also just noticed that std.typecons.Unique does not disable the copy 
constructor. That doesn't seem very safe to me. The source code for it 
is also littered with tons of "Doens't work yet" comments.
Dec 22 2013
prev sibling parent reply "Sergei Nosov" <sergei.nosov gmail.com> writes:
On Sunday, 22 December 2013 at 13:28:05 UTC, Benjamin Thaut wrote:
 Well yes, but I'm more interrested in moving around the 
 ownership between functions, which works in c++11 because of 
 the move semantics they implemented. This doesn't work in D for 
 the shown reasons.
http://dpaste.dzfl.pl/d1a6f7d0 That's as close as I could get. It doesn't move the parameters outside of the function. I workaround it by returning the unique input arguments. It's like "here's your object back". Everything is pretty much safe in safe mode - as long as you don't pass Unique values by reference.
Dec 22 2013
next sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 22.12.2013 14:36, schrieb Sergei Nosov:
 On Sunday, 22 December 2013 at 13:28:05 UTC, Benjamin Thaut wrote:
 Well yes, but I'm more interrested in moving around the ownership
 between functions, which works in c++11 because of the move semantics
 they implemented. This doesn't work in D for the shown reasons.
http://dpaste.dzfl.pl/d1a6f7d0 That's as close as I could get. It doesn't move the parameters outside of the function. I workaround it by returning the unique input arguments. It's like "here's your object back". Everything is pretty much safe in safe mode - as long as you don't pass Unique values by reference.
Uh, this looks a lot better then std.typecons.Unique Did you try doing a pull request to replace std.typecons.Unique with your implementation? Kind Regards Benjamin Thaut
Dec 22 2013
parent "Sergei Nosov" <sergei.nosov gmail.com> writes:
On Sunday, 22 December 2013 at 13:40:30 UTC, Benjamin Thaut wrote:
 Uh, this looks a lot better then std.typecons.Unique
 Did you try doing a pull request to replace std.typecons.Unique 
 with your implementation?
No, I didn't. I'm kind of thinking, that the "unique" concept currently can't be fully implemented as a library solution. It needs at least some language support - disallow refernce usage for safety, make obvious implicit casts for... you know... for kids (currently, when I use this implementation ".unique" and "Unique!T" everywhere kind of clutters the code, and it also adds some burden on writing generic (or just general) code). So, it's kind of an open question.
 You probably want to fix this:
 class C{}
 void main(){
    auto x = unique!C().pack;
    auto y = x.unpack;
    auto z = x.unpack;
    assert(y.irel is z.irel);
}
That's right! Thanks!
Dec 22 2013
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/22/2013 02:36 PM, Sergei Nosov wrote:
 On Sunday, 22 December 2013 at 13:28:05 UTC, Benjamin Thaut wrote:
 Well yes, but I'm more interrested in moving around the ownership
 between functions, which works in c++11 because of the move semantics
 they implemented. This doesn't work in D for the shown reasons.
http://dpaste.dzfl.pl/d1a6f7d0 That's as close as I could get. It doesn't move the parameters outside of the function. I workaround it by returning the unique input arguments. It's like "here's your object back". Everything is pretty much safe in safe mode - as long as you don't pass Unique values by reference.
You probably want to fix this: class C{} void main(){ auto x = unique!C().pack; auto y = x.unpack; auto z = x.unpack; assert(y.irel is z.irel); }
Dec 22 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/22/2013 02:19 PM, Benjamin Thaut wrote:
 When working with C-libraries in D I often wish for a equivalent of the
 C++11 unique_ptr. Unfortunately this is not possible in D. Consider the
 following source code:

 http://dpaste.dzfl.pl/6e71c815

 Is error 1 a bug? Because there should cleary not be any copy at this
 point.
 ...
I don't think the conditions when a struct is moved are actually documented beyond the NRVO case. I think it ideally would be a bug, but this would require some kind of DIP.
 Should we implement moving of u so that error 2 goes away? The compiler
 could move u into the function and move back out afterwards, but that
 would mean that the contents of u would be invalid for the duration of
 the function call (unsafe?)

 Kind Regards
 Benjamin Thaut
The problem is that currently variable 'u' needs to be valid in order to be assigned to. It would be better if it was moved into test2 and then reinitialized. Currently, structs with disabled default construction and postblit are pretty much useless as value types. One has to include some kind of invalid default state. (As Sergei's implementation also does.) Then it is always possible to use explicit moves: import core.stdc.stdio; import std.algorithm; struct UniquePtr{ private int m_i; private bool _valid=false; property bool valid(){ return valid; } disable this(this); this(int i){ m_i = i; _valid = true; } ~this(){ if(_valid) printf("deleting %d\n", m_i); } } UniquePtr test1(){ auto u = UniquePtr(5); return u; } UniquePtr test2(UniquePtr u){ return move(u); } void main(string[] args){ auto u = test1(); u = test2(move(u)); }
Dec 22 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/22/2013 03:13 PM, Timon Gehr wrote:
 Is error 1 a bug? Because there should cleary not be any copy at this
 point.
 ...
I don't think the conditions when a struct is moved are actually documented beyond the NRVO case. I think it ideally would be a bug, but this would require some kind of DIP.
The main issue would probably be internal pointers in safe code.
Dec 22 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/22/2013 03:19 PM, Timon Gehr wrote:
 On 12/22/2013 03:13 PM, Timon Gehr wrote:
 Is error 1 a bug? Because there should cleary not be any copy at this
 point.
 ...
I don't think the conditions when a struct is moved are actually documented beyond the NRVO case. I think it ideally would be a bug, but this would require some kind of DIP.
The main issue would probably be internal pointers in safe code.
Scrap that, it would be disallowed to create them in safe code anyway, and hence the memory corruption would be attributed to the system code that created the pointer.
Dec 22 2013