Re: Why is it possible to call non-const member functions of rvalues but a compile error to modify members or rvalues directly?

2020-06-14 Thread Johannes Loher via Digitalmars-d-learn

On Saturday, 13 June 2020 at 12:47:31 UTC, Stanislav Blinov wrote:

[...]
The temporary exists until the end of full expression, or until 
the end of enclosing statement. It is simply not an lvalue for 
the caller, but it certainly exists, and so its interface must 
function.


So public data members are not part of the interface? I 
understand that it probably doesn't make much sense to mutate 
data members of an rvalue but this just looks very inconsistent 
to me, in particular if you consider the fact that you can also 
call member functions with the = syntax:

```
struct A
{

auto a(int _a)
{
return this._a = _a;
}

int _a = 0;
}

void main
{
static assert(__traits(compiles, { A().a = 2; })); // this is 
ok but looks like it shouldn’t be

}
```


Re: Why is it possible to call non-const member functions of rvalues but a compile error to modify members or rvalues directly?

2020-06-13 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 13 June 2020 at 11:26:58 UTC, Johannes Loher wrote:

Why is it a compile error to set `_a` directly but calling `a` 
just works fine?


If we prevent modifying members of rvalues directly, I would 
also expect calling non-const member functions of rvalues to be 
prevented.


1) Constructors and destructors are also member functions. Surely 
you won't suggest making all constructors `const`, and not being 
able to destruct a temporary? :)
2) The member functions may have useful side effects even on the 
state of temporary.

3) The member functions may serve as factories.

The temporary exists until the end of full expression, or until 
the end of enclosing statement. It is simply not an lvalue for 
the caller, but it certainly exists, and so its interface must 
function. Consider (this code will fail on older compilers, up to 
2.067.0, due to a bug):


void main()
{
import std.stdio : File;
import std.range : iota;
with (File("test.txt", "w"))
{
foreach (n; iota(1, 100, 5))
writeln(n);
}
}

This will open the file, write numbers [1, 96] on their own lines 
in that file, and close it. Both the File and the Iota range are 
temporaries. File can't be `const` as it's a wrapper over FILE*. 
The range can't be const since the foreach mutates it, and it is 
effectively a factory of numbers.




Why is it possible to call non-const member functions of rvalues but a compile error to modify members or rvalues directly?

2020-06-13 Thread Johannes Loher via Digitalmars-d-learn
Consider the following example:

```
struct A
{

auto a(int _a)
{
return this._a = _a;
}

int _a = 0;
}

void main()
{
static assert(!__traits(compiles, { A()._a = 2; }));
static assert(__traits(compiles, { A().a(2); }));
}
```
(https://run.dlang.io/is/GkmpA8)

Why is it a compile error to set `_a` directly but calling `a` just
works fine?

If we prevent modifying members of rvalues directly, I would also expect
calling non-const member functions of rvalues to be prevented.