digitalmars.D - Rvalue forwarding
- Martin Nowak (87/87) Feb 22 2012 Is it possible to forward rvalues through variadic templates?
- H. S. Teoh (12/40) Feb 23 2012 [...]
- Martin Nowak (49/52) Feb 23 2012 A working solution was to let move return a proxy which defers the move
Is it possible to forward rvalues through variadic templates?
Having to "move" the value for every layer is suboptimal.
What am I doing wrong?
----------
import std.algorithm : move;
void foo(Unique!Handle uniq)
{
auto val = uniq.extract;
assert(val._fd == 1);
val.close();
}
void foo(Unique!Handle uniq, string)
{
auto val = uniq.extract;
assert(val._fd == 1);
val.close();
}
version (none)
{
void bar(Args...)(Args args)
{
foo(move(args)); // cannot forward variadic arguments ???
}
}
else
{
void bar(A0)(A0 a0)
{
foo(move(a0));
}
void bar(A0, A1)(A0 a0, A1 a1)
{
foo(move(a0), move(a1));
}
}
void main()
{
Unique!Handle uniq;
uniq = Unique!Handle(Handle(1));
assert(uniq._obj._fd == 1);
bar(move(uniq));
assert(uniq._obj._fd == 0);
uniq = Unique!Handle(Handle(1));
assert(uniq._obj._fd == 1);
bar(move(uniq), "other arg");
assert(uniq._obj._fd == 0);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
struct Handle
{
this(int fd)
{
_fd = fd;
assert(_fd);
}
void close()
{
_fd = 0;
}
~this()
{
assert(!_fd);
}
int _fd;
}
struct Unique(T)
{
this()(auto ref T val) if(!__traits(isRef, val))
{
move(val, _obj);
}
this()(auto ref Unique!T val) if(!__traits(isRef, val))
{
move(val._obj, _obj);
}
disable this(this);
void opAssign(Unique val)
{
move(val._obj, _obj);
}
property T extract()
{
return move(_obj);
}
private:
T _obj;
}
Feb 22 2012
On Thu, Feb 23, 2012 at 08:15:52AM +0100, Martin Nowak wrote:
Is it possible to forward rvalues through variadic templates?
Having to "move" the value for every layer is suboptimal.
What am I doing wrong?
----------
import std.algorithm : move;
void foo(Unique!Handle uniq)
{
auto val = uniq.extract;
assert(val._fd == 1);
val.close();
}
void foo(Unique!Handle uniq, string)
{
auto val = uniq.extract;
assert(val._fd == 1);
val.close();
}
version (none)
{
void bar(Args...)(Args args)
{
foo(move(args)); // cannot forward variadic arguments ???
}
[...]
I'm not sure, but doesn't this only work if foo() is also variadic?
Otherwise I'm not sure how the compiler is supposed to determine, at
compile-time, which overload of foo to call from here. And what if args
contains 3 arguments, or arguments that don't match any overload of foo?
I suppose this *could* be handled by generating runtime code to decide
which foo to call, but from what I understand, D doesn't support this
currently.
T
--
Only boring people get bored. -- JM
Feb 23 2012
On Thu, 23 Feb 2012 08:15:52 +0100, Martin Nowak <dawg dawgfoto.de> wrote:Is it possible to forward rvalues through variadic templates? Having to "move" the value for every layer is suboptimal. What am I doing wrong?A working solution was to let move return a proxy which defers the move until it gets implicitly converted into an rvalue. auto move(T)(ref T src) { /* Non-instantiable non-copyable proxy to forward moves. */ static struct Proxy(T) { static import std.algorithm; ~this() { if (_ptr !is null) { typeid(T).destroy(_ptr); _ptr = null; } } /* Triggers move on implicit conversion. */ property T get() { auto p = _ptr; _ptr = null; return std.algorithm.move(*p); } alias get this; private: disable this(); disable this(this); this(T *p) { _ptr = p; } T* _ptr; } return Proxy!T(&src); } The proxy can be forwarded, but has the downside that one can escape references. auto foo() { int val; return move(val); // ouch } void bar() { { int a; auto m = move(a); } int b = m; // ouch }
Feb 23 2012









"H. S. Teoh" <hsteoh quickfur.ath.cx> 