On Thursday, 25 July 2019 at 20:38:59 UTC, aliak wrote:
On Thursday, 25 July 2019 at 19:35:36 UTC, aliak wrote:
Basically, can template W be made to handle an S that can't be
copied?
import std;
static struct S {
int i;
@disable this(this);
this(int i) { this.i = i; }
}
[...]
So this works - are there any problems with it?
struct W(T) {
T value;
this(T value) {
static if (isMutable!T)
this.value = value.move;
else
this.value = value;
}
}
auto wrap(T)(T value) {
static if (isMutable!T)
return W!T(value.move);
else
return W!T(value);
}
Shouldn't this be happening by default? When would you not want
that to happen?
The way I handle this is with `auto ref` and
`core.lifetime.forward`:
import core.lifetime: forward;
struct W(T)
{
T value;
this()(auto ref T value)
{
this.value = forward!value;
}
}
auto wrap(T)(auto ref T value)
{
return W!T(forward!value);
}
@safe unittest
{
static struct NoCopy { @disable this(this); }
assert(__traits(compiles, {
auto test = wrap(NoCopy());
}));
assert(!__traits(compiles, {
auto lval = NoCopy(); auto test = lval;
}));
}
Interactive: https://run.dlang.io/is/kDJyYC
It's not very well documented, but `forward` does essentially the
same thing as your `static if` + `move` combination.
Note that with both your version and mine, you will run into the
same problem I did of `move` making it impossible to use
instances of `W` in static initializers and CTFE. [1] The best
compromise I was able to come up with was to only call move if
`isCopyable!T == false`, which doesn't really solve the problem,
but at least contains it.
[1] https://github.com/pbackus/sumtype/issues/22