Thank you!
Tejas
notrealemail at gmail.com
Wed Sep 8 06:03:49 UTC 2021
On Wednesday, 8 September 2021 at 05:07:03 UTC, Ali Çehreli wrote:
> On 9/7/21 9:36 PM, Tejas wrote:
>
> >>> S _s;
> >>>
> >>> S s() {return _s;}
>
> [...]
>
> > Do you really think people who are writing code like that
> expect a
> > temporary to be generated?
>
> I think so. Even if they don't, I can't imagine this being a
> big surprise in the future; a little test would reveal that _s
> was not changing.
It's not a big surprise, I agree; but it _is_ a gotcha.
>
> > What else could be the purpose of returning
> > an existing struct and using it as an `lvalue` if not to
> modify it?
>
> The returned copy is not an lvalue; it is an rvalue.
Yes, it is an rvalue, which is then assigned to a temporary and
then that temporary is used as an `lvalue`
```d
auto __temp = s();
__temp.i = 42; //this is what is happening behind the scenes,
according to my knowledge
```
But the user might be thinking that they're modifying `_s`, not
some intermediate temporary.
Again, it can easily be figured out via a small test, so not a
very big deal, but could be a little annoying to discover at
runtime.
>
> > I feel we would be better off if the same
> > ```d
> > <your_var_name> is not an lvalue and cannot be modified
> > ```
>
> rvalues cannot be assigned to
Which is exactly what the original code is doing.
> but they can be modified.
I agree; you taught me that previously in an operator overloading
thread :)
> How? Being value types, structs are consistently passed and
> returned by value. Otherwise, we wouldn't be able to write a
> factory function:
>
> S makeS() {
> return S(); // Should this be returning a reference to a
> temporary?
> }
No, it should return by value, but you wouldn't use it as
```d
makeS().i = 100;
```
And then expect `makeS().i == 100` to be true, would you?
My problem is that the original code returned an _existing_
`struct`, which implies that the struct itself is being returned,
not a duplicate of it(even though after one understands that
`structs` are value types they'll start using `ref S` instead of
`S`).
I'm not saying a function that returns a `struct` should return
the struct by reference; but if that function is being used in
the left hand side of an assignment statement _and_ it is
returning a **named** value(`_s` here), I think its reasonable
for the compiler to at least emit a warning that the value
returned by the function is not usable beyond the scope of that
statement.
And if none of the above convinces anyone
```d
int integer;
int func(){
return integer;
}
void main(){
func() = 30;
}
Output:
onlineapp.d(29): Error: `func()` is not an lvalue and cannot be
modified
```
Please allow this to compile.
`int` is value type, so it is fine to generate a temporary and
allow the code to compile, right? A small test will reveal that
`integer` is not being modified, so it's not **that** big of a
deal, right?
More information about the Digitalmars-d
mailing list