DIP 1016--ref T accepts r-values--Formal Assessment

jmh530 john.michael.hall at gmail.com
Fri Feb 1 03:28:03 UTC 2019


On Thursday, 31 January 2019 at 22:35:26 UTC, H. S. Teoh wrote:
> On Thu, Jan 31, 2019 at 10:26:39PM +0000, jmh530 via 
> Digitalmars-d-announce wrote:
>> On Thursday, 31 January 2019 at 21:57:21 UTC, Steven 
>> Schveighoffer wrote:
> [...]
>> > That being said, you can look at the fact that most people 
>> > don't even know about this problem, even seasoned veterans, 
>> > as a sign that it's really not a big problem.
>> > 
>> 
>> The way you put it makes it sound like a bug...
>> 
>> I don't know if it helps, but below compiles without error.
>> 
>> struct Foo
>> {
>>    private int _x;
>>    int* x() { return &_x; }
>> }
>> 
>> struct Bar
>> {
>>    private Foo _y;
>>    Foo* y() { return &_y; }
>>    void y(Foo foo) { _y = foo; }
>> }
>> 
>> void main() {
>>     Foo a = Foo(1);
>>     assert(*a.x == 1);
>>     *a.x *= 2;
>>     assert(*a.x == 2);
>> 
>>     Bar b;
>>     b.y = Foo(1);
>>     assert(*b.y.x == 1);
>>     *b.y.x *= 2;
>>     assert(*b.y.x == 2);
>> }
>
> Why is it a problem that this code compiles without error?
>
>
> T

Sorry if I didn't really complete my thought.

The code below corresponds to the ref version mentioned above and 
gets the same error originally reported. The only difference is 
that I use Foo instead of Foo* for the getter in Bar. So if you 
instead make that member function a ref function, then it also 
compiles without error (regardless of if you use the 
doubleMyValue function or not).

So they were right that the issue is with the getter. However, 
you're not really protected in any way if you have a ref getter 
at one point in a chain and a non-ref getter somewhere else. 
Making all the getters auto ref also avoids the issue.

struct Foo
{
    private int _x;
    ref int x() { return _x; }
}

struct Bar
{
    private Foo _y;
    Foo y() { return _y; }
    void y(Foo foo) { _y = foo; }
}

void main() {
     Foo a = Foo(1);
     assert(a.x == 1);
     a.x *= 2;
     assert(a.x == 2);

     Bar b;
     b.y = Foo(1);
     assert(b.y.x == 1);
     b.y.x *= 2;
     assert(b.y.x == 2);
}


More information about the Digitalmars-d-announce mailing list