Better handling of noncopyable objects and objects with this(this)

via Digitalmars-d digitalmars-d at puremagic.com
Mon Jun 1 08:32:18 PDT 2015


On Monday, 1 June 2015 at 14:59:38 UTC, Jonathan M Davis wrote:
> On Monday, 1 June 2015 at 14:43:22 UTC, Marc Schütz wrote:
>> On Monday, 1 June 2015 at 14:20:46 UTC, Jonathan M Davis wrote:
>>> On Monday, 1 June 2015 at 12:50:28 UTC, Marc Schütz wrote:
>>>> Also, object with destructors need to have more restrictions:
>>>>
>>>>  S {
>>>>      ~this();
>>>>  }
>>>>
>>>>  void foo() {
>>>>      S s;
>>>>      if(condition)
>>>>          bar(s);
>>>>      // <- should we run the destructor here?
>>>>  }
>>>>
>>>> This can either be solved by making such cases non-eligible, 
>>>> or by "remembering" whether an object was moved using a 
>>>> hidden boolean variable. AFAIK the latter is incidentally 
>>>> the solution Rust chose.
>>>
>>> Wouldn't the compiler just do something like
>>>
>>> if(condition)
>>> {
>>>   bar(s); // Do a move; the destructor is run inside bar
>>>   return;
>>> }
>>> else
>>> {
>>>   s.__dtor();
>>>   return;
>>> }
>>>
>>> In which case, the destructor is always run in the right 
>>> spot, and the compiler can guarantee that a move is done 
>>> rather than a copy?
>>
>> When this can be done, it's of course a good solution. But 
>> when there is additional code between the move and the 
>> destruction, it usually doesn't work:
>>
>>    void foo() {
>>        S s;
>>        if(condition)
>>            bar(s);
>>        baz();
>>        // <- should we run the destructor here?
>>    }
>
> Then, like you suggested, that would indeed appear to require 
> either an invisible bool that indicates whether a move was done 
> or not or disallowing the move. I think that I'd favor the 
> bool, since moving is likely to save more than the extra bool 
> is going to cost.

Yes, and I think an optimizer can even eliminate the cost in some 
cases, e.g. do the rewrite you suggested.

For reference, here are some discussions the Rust community had 
about this topic (didn't read them completely):

https://github.com/rust-lang/rfcs/pull/320
https://github.com/rust-lang/rfcs/blob/master/text/0320-nonzeroing-dynamic-drop.md
https://github.com/pnkfelix/rfcs/blob/a773ba113ba135ddb7f481c4829882733eaa5355/active/0000-remove-drop-flag-and-zeroing.md#require-explicit-drops-rather-than-injecting-them

Some of the suggested solutions are not applicable for us, 
because we don't have to deal with explicit moves like they do. 
But we can certainly learn from their discussions.


More information about the Digitalmars-d mailing list