C++ reference type
David Medlock
ashleymedlock at no.spam.yahoo.com
Sun Jun 25 05:07:14 PDT 2006
Tom S wrote:
> David Medlock wrote:
>
> If it requires you to create workarounds all over the place, makes code
> less transparent than the C++ way and is less efficient, then I'm
> tempted to say that it's worse.
>
>
>
>> You can't opAddAssign in that case yes, but you can add 2 to the
>> first item with:
>>
>> arr2[0] = arr2[0] + 2;
>>
>> Is this really a lot worse? Its maybe 2-3 cycles at the most?
>
>
> It's not about speed in *this* case. The compiler might optimize it
> away. The point is that if you use normal arrays in some place, but then
> decide to switch to your custom classes, you may be in trouble. Say you
> have some myArray which stores structs and somewhere you write:
>
> myArray[i].prop = 5;
>
>
Agreed, changing to a custom class would bite you there.
> You live happily, until one day you find out that your custom logging
> functions are behaving in a weird way. Instead of printing the contents
> of your MyStruct's, they output some ridiculous hexadecimal numbers. You
> jump into the code just to find out (after some struggles), that the
> wrong logging function was called, because you have
>
> void log(MyStruct);
> and
> void log(void*);
>
> and somewhere in your code you had log(myArray[i]). No error was
> reported because the compiler silently assumed that you wanted to print
> a pointer.
>
>
>
>>> This gets worse, e.g. if you have a
>>>
>>> struct Foo {
>>> int bar;
>>> }
>>>
>>> Foo[] arr3; ... ; arr3[0].bar = 1;
>>>
>>> but when you define
>>>
>>> Array!(Foo) arr4; ... ;
>>>
>>> then to accomplish the 'arr4[0].bar = 1;' functionality, you have to
>>> make opIndex return a pointer. Yet then you can't say 'Foo x =
>>> arr4[0];' because there's a type mismatch. You'd have to dereference
>>> the pointer.
>>
>>
>> Not to pick but you could say:
>>
>> auto x = arr4[0];
>> x.bar = 100;
>
>
> You could with classes, but in this case typeof(arr4[0]) is a struct.
>
I meant in the case you returned a pointer, but yes that wouldn't follow
the 'native' array semantics so it wouldn't be good to return a pointer.
Maybe with the static if you could make your container behave
different with non-object types?
>
>
>> or you could simply use a different method:
>>
>> class Array(T)
>> {
>> T[] items;
>> ...
>> T* ptr(int n=0) { return items.ptr + n ; }
>> }
>>
>> arr.ptr[5].bar = 1;
>>
>> Since the built int arrays use a .ptr property, I usually define this
>> method anyways. Once you use it for a while its second nature.
>
>
> Yet I don't feel like losing array bounds checking... It would have to
> be 'arr.ptr(5).bar = 1;' plus a modification to the 'ptr' function. But
> then it doesn't read as 'arr[5].bar = 1;'.
>
> At the moment the language doesn't provide enough abstraction in this
> area. At least IMO.
>
>
Agreed. There is a lack there.
It just hasn't bit me a lot thus far (and I have written a fair amount
of code in D). I don't see a clear solution short of reference/inout
returns, but I wonder what that would do to the rest of the language
semantics.
I can't recall if Walter said why he didn't include them.
>
>> If you want to get crazy:
>>
>> void opIndexAssign( void delegate(T* item) fn, int n )
>> {
>> fn( items.ptr + n );
>> }
>>
>>
>> then:
>> arr[0] = (Foo* f){f.bar += 3;};
>>
>> hehe :P
>
>
> Ummm... no, thanks :P
>
Tongue in cheek example of course, but I'm so far liking the delegate
syntax.
>
>
>> Seriously though, if the item is small enough to not warrant a class,
>> then just extend the container class and define a custom method to
>> update the item.
>
>
> That's a corner case which misses the point a bit...
>
I meant that usually your algorithm entails a bit more than just
updating a single member of a struct. In that case hiding the use of a
pointer would be IMO ok.
We aren't really disagreeing on any implementation details, only on
their impact on daily use.
Cheers.
-DavidM
More information about the Digitalmars-d
mailing list