I need some help here.

Reiner Pope reiner.pope at REMOVE.THIS.gmail.com
Thu Aug 31 00:02:28 PDT 2006


Chris Nicholson-Sauls wrote:
> Damian wrote:
>> Suppose I have a class like this:
>>
>> class cl{
>>     private:
>>         char[][] _data;
>>         int _maxDataLength;
>>     public:
>>         char[][] data(){
>>             _return data;
>>         }
>>         void data(char[][] d){
>>             _maxDataLength = calculateMaxDataLength(d);
>>             _data = d;
>>         }
>>         int maxDataLength(){
>>             return _maxDataLength;
>>         }
>>     private:
>>         int calculateMaxDataLength(char[][] data){
>>             // this takes time.
>>         }
>> }
>>
>> And in a function I do something like this:
>> // dClass is a global cl object.
>>
>>     char[][] d = dClass.data;
>>     d[3] = "naranja";
>>     int dlength = dClass.maxDataLength;
>>
>> then dlength won't be valid, since _data has changed but
>> _maxDataLength wasn't updated.
>>
>> How can I avoid this?
>> I know that
>>         int maxDataLength(){
>>             return calculateMaxDataLength(_data);                    }
>>
>> will solve the problem, but I don't want to call 
>> calculateMaxDataLength if the intention is to to see the data without 
>> modifying it.
>>
>> Thanks.
> 
> Two ways.  First way, if it makes sense you might overload the index 
> operators for your class.  If that doesn't make logical sense, then 
> there is the .dup property which will create a safe copy:
> 
> # char[][] data () {
> #   return _data.dup;
> # }
> 
> I don't remember ever using .dup with multi-dimensional arrays, though, 
> so it may have to be something more like:
> 
> # char[][] data () {
> #   char[][] copy;
> #   copy.length = _data.length;
> #   foreach (i, x; _data) {
> #     copy[i] = x.dup;
> #   }
> #   return copy;
> # }
> 
> I would say experiment with the first one first.  I imagine it should 
> work fine, and is certainly less work than the second.
> 
> -- Chris Nicholson-Sauls

This is really the immutability problem again. Basically, you want to 
either:
- not allow modification of _data; or
- be aware when _data is changed.

Chris's suggestion (dup'ing it) achieves the first, and providing the 
index operator achieves the second by intercepting indexing calls.

Another suggestion, if you don't want to overload indexing for your 
class is to create an array wrapper which notifies your class on changes:

class MyArray(T) {
	private T[] _data;
	
	T opIndexAssign(uint index, T value) {
		notifyThatDataHasChanged();
		return _data[index] = value;
	}

	T opIndex(uint index) {
		return _data[index];
	}
	...
}

This means that you can use your class's opIndex for something else. 
Alternatively, you could use this interface to return an immutable 
version of _data, just by not supporting opIndexAssign.

Cheers,

Reiner



More information about the Digitalmars-d-learn mailing list