On 12/18/2016 05:14 AM, Picaud Vincent wrote:

> Another interrogation for me, who come from C++, is how to translate
> into D:
>
> template<typename T> void foo(T&& t);

If it means "rvalue reference"[1], then there is no equivalent is D because D does not allow references to rvalues, even if const.

If the purpose is optimization, the good news are

* Classes are already reference types so there is no lvalue or rvalue reference distinction there

* rvalue structs are automatically moved to functions when passed by-copy

import std.stdio;

struct S {
    double i;
    ubyte[1000] buf;
    this(int i) {
        this.i = i;
        writefln("constructor       %s", i);
    }
    this(this) {
        writef(  "post-blit         %s -> ", i);
        this.i += 0.1;
        this.buf = buf.dup;
        writeln(i);
    }
    ~this() {
        writefln("destructor for    %s", i);
    }
}

void foo(S s) {
    writefln(    "foo(by-copy)      %s", s.i);
}

void foo(ref const(S) s) {
    writefln(    "foo(by-ref-const) %s", s.i);
}

// UNCOMMENT THIS TO BE SURPRISED:
// void foo(ref S s) {
//     writefln(    "foo(by-ref)       %s", s.i);
// }

void main() {
    {
        writeln("\n--- rvalue ---");
        foo(S(1));
    }
    {
        writeln("\n--- mutable lvalue ---");
        auto s = S(2);
        foo(s);
    }
    {
        writeln("\n--- const lvalue ---");
        const s = S(3);
        foo(s);
    }
}

According to the output, there is no post-blit executed for the rvalue:

--- rvalue ---
constructor       1
foo(by-copy)      1
destructor for    1

--- mutable lvalue ---
constructor       2
post-blit         2 -> 2.1
foo(by-copy)      2.1
destructor for    2.1
destructor for    2

--- const lvalue ---
constructor       3
foo(by-ref-const) 3
destructor for    3

There is a surprising difference in D:

* First, in C++, you cannot have both the by-copy and by-ref-to-const overload of a function: It would be ambiguous for rvalues.

* You can have that in D, which brings the interesting difference:

In D, non-constness of an object seems to be more important in overload resolution: Notice how mutable lvalue above is passed to by-copy instead of the potentially-more-optimal by-const-ref above. D realizes that a mutable object is for mutation and because by-const-ref cannot mutate it, D passes it to the by-copy function. (This may be seen as a bug by some.)

Interestingly, enabling the by-mutable-ref overload above, now the mutable object goes to by-ref and there is no automatic copy:

--- rvalue ---
constructor       1
foo(by-copy)      1
destructor for    1

--- mutable lvalue ---
constructor       2
foo(by-ref)       2
destructor for    2

--- const lvalue ---
constructor       3
foo(by-ref-const) 3
destructor for    3

Ali

[1] I have an issue with "rvalue reference" as rvalue references can be references to lvalues as well. :p

Reply via email to