disable all member function calls for rvalues?

Michel Fortin michel.fortin at michelf.com
Fri Dec 18 05:10:18 PST 2009


On 2009-12-17 23:57:09 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail at erdani.org> said:

> There is a wart in D I'd like to eliminate. Unfortunately, that would 
> also eliminate some valid uses.
> 
> The problem is as follows. "ref" values in function parameter lists are 
> always bound to lvalues - never rvalues. This is, except for _one_ case:
> "this" in member functions.
> 
> struct A {
>     void fun() {
>        ...
>     }
> }
> 
> A gun() { return A(); }
> 
> unittest {
>     gun().fun(); // works
> }
> 
> This doesn't sound so bad until the following happens:
> 
> struct A {
>     ref A opAssign(ref A rhs) { ... }
> }
> 
> struct B {
>     @property A a() { ... }
> }
> 
> unittest {
>     B b;
>     b.a = A.init;
> }
> 
> Everything looks kosher, but the problem is b.a returns a temporary, 
> and then that temporary is assigned to. The assignment is inoperant.

Inoperant? Not necessarily. Assigning to temporaries like that is used 
sometime in C++ when a temporary "proxy" object is returned, the 
temporary object just forwarding the assignment to the right place. 
Calling any function on a temporary could have "side effects", and 
those "side effects" might effectively be the main desired effect.

Which makes me think that the same applies to rvalues being bound to 
ref: they could be temporary proxies too, or other types with side 
effects.


> For this and other related reasons I'd like to disallow binding 
> temporaries to "this". There are cases in which you'd want to, and 
> you'd have to insert explicit variables. But I think eliminating the 
> binding is the right thing to do.

I agree with you that the dissimilarity for this and other arguments is 
not desirable.

Personally, I would allow rvalues to convert to non-const ref. There 
are as many valid uses for temporaries passed as arguments (like the 
proxy object) than there are for temporaries passed as "this".

If you really want to disallow ref temporaries, then I'd suggest having 
some kind of flag allowing us to opt-in specific types. Only those 
types would be allowed as non-const ref temporaries. But it seem to me 
that we already have enough flags to deal with in D.

Which makes me think of another problem with forcing const: unlike C++, 
our const is transitive. This means that if your temporary is just some 
kind of smart pointer to somewhere, forcing it to be const would 
prevent any modification of the data it points to. Simple synthetic 
example:

	RefCountedPtr!MyObject getAnObject();

	void test(ref RefCountedPtr!MyObject object) {
		object.mutate(); // method that requires a mutable object
	}

	test(getAnObject);

Anything of the sort can't work if you force the argument to be const. 
In C++ you can make ref const with not much consequence because const 
is not transitive. But not in D.

I'm all for detecting unintended uses of rvalues, but I think forcing 
ref to be const is a mistake, both for "this" and other arguments. We 
need another solution.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/




More information about the Digitalmars-d mailing list