WTF did happen with struct constructor and ref in 2.061 ?
Ali Çehreli
acehreli at yahoo.com
Fri Jan 4 11:15:02 PST 2013
On 01/04/2013 10:48 AM, deadalnix wrote:
> On Friday, 4 January 2013 at 16:47:38 UTC, Jonathan M Davis wrote:
>>> There is no semantic difference between
>>>
>>> S s = S(2); foo(s)
>>>
>>> and
>>>
>>> foo(S(2));
>>
>> There's a _huge_ difference between those two. In the first case, you
>> have a
>> variable which exists beyond the end of the function call. In the
>> second, you
>> have temporary which is destroyed as soon as the statement has
completed.
Still, there is no semantic difference. I know this issue from C++. At
first I had embraced it but I am not so sure anymore. The language is
getting out of its way to protect the programmer. A language like C++
that gives so much freedom to do many other unsafe things...
Constructors and functions do not affect objects alone. However frowned
upon, a function that is called on an S may have side-effects that are
beyond the object itself. If foo() does s.bar() and S.bar has a
side-effect, I wouldn't care about the changes on the rvalue object itself.
So, I think C++ could have allowed binding rvalues to references to
non-const. I don't think I would be bothered with that. If I had fooled
myself occasionally, so be it.
>> Where there's no real difference is
>>
>> foo(S(2));
>> foo(funcThatReturnsS());
Agreed.
>>
>
> This may not have a storage :
> foo(funcThatReturnsS());
I don't see that. funcThatReturnsS returns an S, which must have a
storage as well.
> This MUST have a storage (as this storage is passed to the ctor) :
> foo(S(2));
>
> So it is in fact different.
>
>> Also, it's completely nonsensical for a function which is supposed to be
>> taking its argument by ref to take temporaries. A function takes its
>> argument
>> by ref so that it can mutate it, and if it accepts rvalues, then you
>> lose the
>> changes, because you're not dealing with a variable that lasts
beyond the
>> statement that the function call is in.
Getting back to this issue: So what? I have one more bug in my code.
> A function can take ref argument for performance reasons. A function
> caller may not care about reading the changes.
>
> Yes, if it for performance, auto ref should be used, but why in the
> first place a breaking change have been made BEFORE auto ref is sorted
> out ?
I agree with all of that. (Although, the French grammar rule of that
space before the question mark is hurting my eyes! :p)
>> If the issue is that someone wants the function to avoid making copies
>> of the
>> argument if it's not necessary, then that's what auto ref is for (and
>> why the
>> discussion how to implement that for non-templated functions is so
>> important),
I hope D's 'auto ref' solution solves this issue once and for all. :)
> struct Bar {
> uint i;
>
> this(uint foo) {
> import std.stdio;
> writeln(&this);
> }
> }
>
> void main() {
> Bar(0);
> }
>
>> There should be _zero_ difference between how a struct literal is
>> treated and how the return value of a function is treated. Both are
>> temporaries and should be treated as such.
>>
>
> Code above show there is.
I don't see that. There is storage for the rvalue returned from
funcThatReturnsBar() as well, no?
struct Bar {
uint i;
this(uint foo) {
import std.stdio;
writeln(&this);
}
}
void foo(Bar bar)
{}
Bar funcThatReturnsBar()
{
return Bar(1);
}
void main() {
foo(Bar(0));
foo(funcThatReturnsBar());
}
That program prints two addresses for me:
7FFFF1076290
7FFFF1076298
Ali
More information about the Digitalmars-d
mailing list