getters and setters not an lvalue

monarch_dodra monarchdodra at gmail.com
Wed Oct 31 09:42:25 PDT 2012


On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme 
wrote:
> In my current code I'd like to do something ala:
>
> void main(){
> 		getsettest test=new getsettest();
> 		
> 		test.value+=1;
> }
>
> class getsettest{
> 	int myvalue;
> 	
> 	this(){
> 	}
> 	
> 	@property{
> 	
> 		int value(){
> 			return myvalue;
> 		}
> 		
> 		void value(int value){
> 			myvalue=value;
> 		}
> 	}
> }
>
> but this gives the following error:
> test.d(4): Error: test.value() is not an lvalue
>
> Is there a rationale behind this decision of not translating
> test.value+=1 to test.value= test.value +1 ?

It's not that simple as "test.value" is not an LValue, so from 
the compiler's perspective "test.value = test.value + 1" calls 
two different functions, that may or may not have anything to do 
with each other.

The expansion "++ => +=1 => a = a + 1" works if there is only 1 
lvalue the whole chain through.

Can the compiler really assume it can do that? And is it a smart 
move to allow it to make that assumption. What you have there is 
basically an encapsulated field, that does not leak its address:

You can take the filed, you can update it with a new value, but 
you can't modify it.

If you allow "test.value+=1", then where does it end?

Is this legal?
//----
void foo(int& a) {...}
foo(test.value);
//----

Would you want the compiler to expand it into:
//----
void foo(int& a) {...}

//scope for __temp
{
   auto __temp = test.value;
   foo(temp);
   test.value = temp;
}
//----

--------------------
IMO, if you take the time to write both functions, instead of 
just:
//----
@property ref int front(){return myvalue;}
//----
Then the compiler must assume you did it for a reason, and not 
mess with your code.


More information about the Digitalmars-d-learn mailing list