ref returns and properties

Denis Koroskin 2korden at gmail.com
Mon Jan 26 15:18:11 PST 2009


On Tue, 27 Jan 2009 01:52:26 +0300, Steven Schveighoffer <schveiguy at yahoo.com> wrote:

> "Andrei Alexandrescu" wrote
>> Steven Schveighoffer wrote:
>>> I guess I'm not really sure what the "acquire" method does.  I saw you
>>> mention it in another post, but with no explanation as to what it
>>> actually does, just that it was needed.  I'm sure I'm not getting what
>>> should be obvious, but if you could enlighten, I would appreciate it :)
>>
>> Say you have an object obj that has a Matrix property and you have a
>> Matrix object handy. The Matrix is rather resource intensive so you'd
>> rather not copy it unwittingly. Conventionally, if you say:
>>
>> Matrix m;
>> ... fill matrix ...
>> obj.matrix = m;
>>
>> then m is copied into obj.matrix (there is the by-value call to set
>> property). Now it's possible to arrange things such that m is
>> destructively copied, but as the auto_ptr disaster has shown, it's not
>> that intuitive to make assignment destroy the right hand side.
>>
>> So we'd need a distinct method:
>>
>> obj.matrix.acquire(m);
>>
>> That method takes the matrix by reference, sucks its life out of it, and
>> leaves an empty shell behind. Pretty much like in your average horror
>> movie.
>
> So what you are saying is that you want to control the set such that it
> destroys the source (essentially, I'm reading, you don't want to do a  
> deep
> copy, just a reference copy, and then null the original reference).
>
> Let me ask another question then... does a property have reason to have  
> both
> set AND acquire?  More specifically, does a function that takes a  
> property
> as an argument as we have been discussing need both set and acquire  
> passed
> to it?  If not, you can simply pass the set method that you want, still  
> only
> requiring a pair of functions.  How to signal that to the compiler  
> easily?
> Not so sure... but it does seem to me like a type should know how it  
> should
> be copied, and likely doing it other ways should require special methods.
>
> I can think of possible library solutions to this, say a wrapper property
> struct that can call any two functions to do set or get.
>
>>
>>> Having the two functions seems like a reasonable baggage compromise, if
>>> you want to control the get and set methods of a property and pass that
>>> control to an underlying function, you need at least that.  If we start
>>> generalizing it to anything, then it starts looking like struct
>>> interfaces would be more suitable.  For example, you could allow  
>>> setting
>>> an int property using both an int and a string, do you want to pass  
>>> both
>>> setters to a function?  I think limiting it to just a set and a get
>>> function should be sufficient.
>>
>> With only get and set I can't implement a nothrow swap, which kinda  
>> bends
>> me out of shape.
>
> Sorry, don't get that either.  Why can't set and get be used in a nothrow
> swap?
>
> -Steve
>
>

Because set implies data copying (read: allocation) and copy constructor call, both of which can throw.

How about the following - you call a swap with a dot syntax:

int x = 42;
int y = 13;

x.swap(y); // calls global void swap(T)(ref T, ref T); or a specialized version, swap(ref int, ref int);

User is, however, free to implement his own swap method:

struct BigInt
{
    ...
    void swap(ref BigInt other) { ... }
    ...
}

Or another way - "void swap(T)(ref T lhs, ref T rhs);" tries "lhs.swap(rhs);" first, and falls back to "auto tmp = lhs; lhs = rhs; rhs = tmp;" if no lhs.swap method is defined.
This way you can define "void aquire(ref T newOwner, ref T data);" as "newOwner.aquire(data);" and fall back to "swap(newOwner, data); release(data);" on failure.
"void release(ref T obj);" tries "obj.release();" first and falls back to "swap(obj, T());" or "obj = T();" on failure.





More information about the Digitalmars-d mailing list