tl;dr: How do you do perfect forwarding in D?
The link has a great explanation, but for example, let's say I have this method:
void foo(T)(in int a, out int b, ref int c, scope int delegate(ref const(T)) d)
const nothrow
{
}
How do I create another method, bar()
, which can be called in lieu of foo()
, which subsequently calls foo()
"perfectly" (i.e. without introducing compilation/scope/etc. problems at the calling site)?
The naive approach
auto bar(T...)(T args)
{
writeln("foo() intercepted!");
return foo(args);
}
of course doesn't work because it doesn't handle the ref
, in
, out
, inout
, the const
-ness of the method, pure
-ity, nothrow
, etc... and it also limits how the values can be used with r-values.
And I don't know how to handle those possible cases... any ideas?
Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.
We use std::forward to retrieve the original value category. If for the handler we provided an rvalue then insert will move from it. If for the handler we provided an lvalue then insert will copy it. There are a lot of rules that come into play for the initial deceivingly simple code.
The std::forward function as the std::move function aims at implementing move semantics in C++. The function takes a forwarding reference. According to the T template parameter, std::forward identifies whether an lvalue or an rvalue reference has been passed to it and returns a corresponding kind of reference.
An lvalue (locator value) represents an object that occupies some identifiable location in memory (i.e. has an address). rvalues are defined by exclusion. Every expression is either an lvalue or an rvalue, so, an rvalue is an expression that does not represent an object occupying some identifiable location in memory.
Your naive approach can be improved upon, though it's still not perfect:
auto ref bar(T...)(auto ref T args)
{
writeln("foo() intercepted!");
return foo(args);
}
Now the only problem is scope
arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With