On Saturday, 24 March 2018 at 17:30:35 UTC, Manu wrote:
On 24 March 2018 at 04:57, John Colvin via Digitalmars-d
<[email protected]> wrote:
On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote:
Forked from the x^^y thread...
On 23 March 2018 at 12:16, Walter Bright via Digitalmars-d
<[email protected]> wrote:
On 3/23/2018 11:09 AM, Manu wrote:
[...]
Rvalue references are not trivial and can have major
unintended consequences. They're a rather ugly feature in
C++, with weirdities. I doubt D will ever have them.
Can you please explain these 'weirdities'?
What are said "major unintended consequences"?
Explain how the situation if implemented would be any
different than
the workaround?
This seems even simpler than the pow thing to me.
Rewrite:
func(f());
as:
{ auto __t0 = f(); func(__t0); }
I understand what you want, but I'm struggling to understand
why it's such a huge deal.
Because it makes this kind of D code that interacts with C++
objectively worse than C++, and there's no reason for it.
You can't say to someone who just frustrated-ly doubled their
line
count by manually introducing a bunch of temporaries in a tiny
function that appears to do something so simple as 'call a
function',
that "oh yeah, isn't it cool that you can't just call your
functions
anymore! isn't D cool! we should switch to D right?"
It's embarrassing. I've been put in the position where I have
to try
and 'explain' this feature quite some number of times... they
usually
just give me 'the look'™; ya know, quietly wondering if I'm
still
sane, and all I end up with is someone who's about 95% less
convinced
that D is cool than they were 5 seconds beforehand.
What pisses me off is that's such a pointless thing to happen,
because
this issue is so trivial!
In my experience, people are evaluating how D will materially
impact
the exact same code they're already writing in C++. This is one
of
those ways that they will be materially impacted, and it's
almost
enough all on its own to cause people to dismiss the entire
thing on
the spot.
Pretty much the best case at this phase is that the D code is
exactly
the same as C++. If we can trim off a few parens here and there
(ufcs?), maybe remove some '::' operators (modules that don't
suck),
that's a huge win.
The reason you want to pass by reference is for performance,
to avoid copying the data at the call boundary.
So there are 2 cases: an lvalue needs to be passed, or an
rvalue needs to be passed.
1. The address of the lvalue is passed.
2. The rvalue is copied to a local, then the address of that
local is passed.
So in the rvalue case, you're not getting the performance
benefit of passing by reference, because you have to copy to a
local anyway.
What I would do in D currently to get the same performance and
API:
void foo(float[32] v) { foo(v); }
void foo(ref float[32] v) { ... }
or
void foo()(auto ref float[32] v) { ... }
Can't be extern(C++), can't be virtual either (both is likely).
I said before; you're talking about Scott Meyers 'universal
references' as a language concept, and I'm just talking about
calling
a function.
but I dont' get how or why. It's exactly D's solution to the
problem.
It doesn't solve the problem... it doesn't even address the
problem. You're talking about a totally different thing >_<
Auto ref allows the unnecessary copy to be avoided for lvalues
and creates a temporary (as part of passing the value) for
rvalues. It has downsides (virtual functions and extern(C++), but
it does directly address the problem you're talking about, unless
I have totally misunderstood you.
Here is a small proof of concept I made to demonstrate how easy
it seems to be to use `auto ref` to call a C++ virtual const&
function without incurring any more copies than would happen with
the same calls from C++. I'm sure it could be improved a lot, but
does the basic concept match what you would need?
// D source file:
/// mix this in to your extern(C++) class with a list of the
functions where you
/// want to be able to pass rvalues to ref parameters.
auto rValueRefCalls(Funcs ...)()
{
string ret;
foreach (foo; Funcs)
ret ~= `extern(D) void ` ~ __traits(identifier, foo) ~
`(Args ...)(auto ref Args args)
if (__traits(compiles, (&this.` ~ __traits(identifier, foo) ~
`)(args)))
{
(&this.foo)(args);
}`;
return ret;
}
extern(C++)
{
class A
{
void foo(const ref int v);
mixin(rValueRefCalls!foo);
}
A makeA();
}
void main()
{
int x = 3;
auto a = makeA();
a.foo(x);
a.foo(3);
}
// C++ source file:
#include<cstdio>
class A
{
public:
virtual void foo(const int& v)
{
printf("%d\n", v);
}
};
A *makeA()
{
return new A;
}