temporary objects are not allowed to be pass by ref anymore

Denis Koroskin 2korden at gmail.com
Wed Apr 29 02:35:28 PDT 2009


On Sun, 19 Apr 2009 23:52:02 +0400, Andrei Alexandrescu <SeeWebsiteForEmail at erdani.org> wrote:

> Now onto why ref was disallowed to bind to an rvalue. This is because  
> some functions take things by ref intending to change them. Passing an  
> rvalue is in such cases a bug.
>
> I agree there are functions that only want to use ref for speed  
> purposes. I suggested Walter to use ref? for those. ref? means it could  
> be an rvalue or an lvalue.
>
>
> Andrei

I don't understand why it is a bug, could you please elaborate on it?

But anyway, why disallow pass-by-const-ref? It won't be modified anyway!

struct Rect
{
    int x, y, w, h;
}

Rect get()
{
    Rect r;
    return r;
}

void pass(ref const(Rect) rect)
{
}

void main()
{
    pass(get());
}

Error: function test.pass (ref const(Rect) rect) does not match parameter types (Rect)
Error: get() is not an lvalue

Also note that if you are right, and modifying a temporary is a bug, then C++ is in a winning position here, because its const system is tail-const, and that's exactly what is required here - you can't modify a variable, but you can mofify whatever it points to.

We could have this behavior, too, by passing final-ref, not const-ref. Final qualifier means that an object it is applied to won't be modified, but it makes no statements about transitivity. Essentially, that's what C++ const does.

Here is an example:

struct RefCounted(T)
{
    T* obj; // includes "int numReferences;" intrusively.
}

void passObject(ref final(RefCounted!(Foo)) foo)
{
    auto copy = foo; // increments reference counter. Note that this don't modify the foo itself, only object which is available through it.
}

// passObject(new Foo()); // doesn't work, can we do anything with it? I'd like to hear your ideas.
passObject(RefCounted!(new Foo())); // allowed!



More information about the Digitalmars-d mailing list