Parameter forwarding
Kostiantyn Tokar
tokarkonstantyn at yandex.ua
Thu Oct 14 16:53:17 UTC 2021
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?
More information about the Digitalmars-d-learn
mailing list