On Thursday, 25 July 2019 at 21:23:33 UTC, Paul Backus wrote:
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
Haha. Ironic. Thanks, again :)
Though, if you use auto ref, and you check if it's mutable and
not copyable and then move, then that means you could potentially
be applying move to an object on behalf of the clients
auto a = MyUnmovableType()
auto b = LibraryType(a);
writeln(a); // ??
If this is a problem, I guess a __traits(isRef, parameter) check
along with mutable and copyable could help. Then if client want
it moved they could call move explicitly.