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;
}

Reply via email to