Hello.

I'm concerned about D's move semantics and how Phobos supports it. For example, `std.typecons.Tuple`.
```d
struct A
{
    int i;
    this(this) { writeln("Expensive copy"); }
}

void main()
{
    auto t = Tuple!(A)(A(42));
}
```
This code produces 1 unnecessary copy. Argument is an rvalue and can be passed by move. Indeed, one copy is elided when rvalue argument binds to constructor parameter, but then it became an lvalue. Take a look at `Tuple` [constructor](https://github.com/dlang/phobos/blob/4130a1176cdb6111b0c26c7c53702e10011ff067/std/typecons.d#L672).
```d
this(Types values)
{
    field[] = values[];
}
```
Actual fields are constructed from lvalues. Why there is no `auto ref` and `forward`? It looks like there is no way to construct a tuple without copying.

But it gets even worse, because factory function `tuple` creates another level of indirection and produces 2 copies from an rvalue.

C++'s tuples perform perfect forwarding. If class implements a move constructor, then neither tuple's constructor nor `make_tuple` produce copies. [Example](https://onlinegdb.com/sz0NhNNf2). Price for that is separate move constructor, but at least there is a way to avoid copying.

But this pattern is common in Phobos. This UFCS chain produces 17 copies. But should it?
```d
only(A(0), A(1), A(2))
        .filter!(a => a.i == 1)
        .takeOne
        .front;
```
[Code](https://run.dlang.io/is/thEFC2)

So is there no way to utilize move semantics using Phobos? Why forwarding is so neglected?

Reply via email to