rvalues -> ref (yup... again!)
John Colvin
john.loughran.colvin at gmail.com
Sat Mar 24 23:03:36 UTC 2018
On Saturday, 24 March 2018 at 17:30:35 UTC, Manu wrote:
> On 24 March 2018 at 04:57, John Colvin via Digitalmars-d
> <digitalmars-d at puremagic.com> 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
>>> <digitalmars-d at puremagic.com> 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;
}
More information about the Digitalmars-d
mailing list