Discussion: Rvalue refs and a Move construtor for D
kinke
noone at nowhere.com
Wed Sep 4 19:01:54 UTC 2019
On Wednesday, 4 September 2019 at 18:43:08 UTC, Manu wrote:
> On Wed, Sep 4, 2019 at 7:50 AM Suleyman via Digitalmars-d
> <digitalmars-d at puremagic.com> wrote:
>>
>> On Wednesday, 4 September 2019 at 00:58:44 UTC, Manu wrote:
>> > Move semantics aren't a feature of the move constructor, they
>> > are USED
>> > BY the move constructor.
>> > You can move an argument to any function. Consider a
>> > unique_ptr, which
>> > can only move. It would be impossible to pass a unique_ptr to
>> > any
>> > other function than the move constructor itself.
>>
>> If you can get the move constructor and move assignment in
>> addition to an intrinsic function for moving lvalues to
>> rvalues then you can do move semantics without rvalue ref.
>>
>> unique_ptr in C++ doesn't move itself magically. You have to
>> eplicitly move it by calling `move()`. Example:
>> https://cpp.godbolt.org/z/8jVONg.
>> You can do that with the machinery provided in the POC without
>> rvalue ref.
>
> You misunderstood what I'm saying.
> I'm saying that it can't only be a `@move` constructor that can
> accept
> rval references, any argument should be able to be one.
> Functions may
> have multiple arguments, and some of them may be unique_ptr-like
> objects.
> If you accept by-value, and you use a move-constructor to
> construct
> the argument, then we're back at making a copy at every level
> of the
> callstack, and that's specifically what we need to avoid.
Nope, Suleyman is totally right here. Move constructors are in
fact never ever used to construct a parameter from an argument.
The only time a move ctor is called is for `auto var =
std::move(otherVar)`. That's how C++ handles it, and that's how
an improved D could handle it as well, without rvalue refs in the
language.
// high-level: by value
// low-level: just gets 2 pointers to temporaries and directly
manipulates those,
// no copying or moving at all
void func(T)(UniquePtr!T a, UniquePtr!T b);
void foo(T)(UniquePtr!T a) // again, `a` is a ref to a temporary
{
// forward the `a` ref; construct a new UniquePtr and forward
its address
func(move(a), makeUnique!T());
}
void bar(T)()
{
// Construct a new UniquePtr and forward its address to `foo`.
// In the end, manipulating `a` in `func` will manipulate
this temporary here, across 2 calls.
foo(makeUnique!T());
}
For this to work, UniquePtr wouldn't need a move ctor. This is
just an ABI detail (and requires a `move` intrinsic, as stated
multiple times already).
More information about the Digitalmars-d
mailing list