Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
June 13, 2006 struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
A little report on recent tamperings with D. I often deal with primitive types which are "vector spaces". Examples * 3D-vectors * colors * quaternions * matrices. While these are distinct types with distinct operations, they all have in common that they can add and subtract members of their kin, and multiply them with a scalar. They also have a zero (neutral) element. This is what the term vector space is mathematically about. In the C++ world, I was so annoyed that I had to type the same boilerplate stuff over and over again for each of these types that I invented my "vector space" template system. With this system it is possibly to declare a vector space type with minimum effort and have all the basic operations ready to go. It seems I cannot port this system to D with the current state of D. The short story is I need either - struct inheritance or - anonymous unions outside an aggregate in a mixin I would prefer struct inheritance: struct field { union { ... }; union { ... }; union { ... }; }; struct vectorspace : field { // have anonymous unions of "field" injected into this scope } but I since there is no struct inheritance, I tried with mixins template field { union { ... }; union { ... }; union { ... }; }; struct vectorspace { mixin field; } But you cannot have anonymous unions outside a struct :/( So I'm struck at this point. Moreover, the mixin approach is not feasible because then you cannot make field a template parameter. template( field ) { struct vectorspace only seem to work when field is a type, not a mixin. I would like to weigh in for struct inheritance, since it seems a trivial thing to allow. C programmers have often done this by declaring a variable of the base type as the first member of the struct. So I was a little surprised that D has no inheritance for plain data structs. There is more missing in D that prevents me to port the system fully: - explicit return by reference (return an L-value) - struct constructors These are not showblockers, but missing them is ugly! I see from the archives that struct constructors have been discussed already, so count me as another vote for struct constructors here. The explicit L-value return however I think is an important concept that is missing with subtle implications. Without it, user defined types can never be made transparent to builtin types. Consider: int a; (+a) = 3; The unary plus operator returns an L-value, so the assignment can take place. In C++, you can define the unary + operator to behave the same for your type, by defining both R-value and L-value operator: // R-value unary + const mytype &operator +( const mytype &object ) { return object; } // L-value unary + mytype &operator +( mytype &object ) { return object; } In D, you can only do the R-value version. |
June 13, 2006 Re: struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
Posted in reply to cschueler | In article <e6l2mu$1242$1@digitaldaemon.com>, cschueler says... >I would like to weigh in for struct inheritance, since it seems a >trivial thing to allow. C programmers have often done this >by declaring a variable of the base type as the first member >of the struct. So I was a little surprised that D has no >inheritance for plain data structs. > >There is more missing in D that prevents me to port the system fully: > >- explicit return by reference (return an L-value) >- struct constructors > I've had to deal with my share of vector/matrix classes. I personally hate writing the damn things, since they are so tedious. I'd hoped array ops or something like that would provide a native solution, but I don't think it's gonna happen any time soon. Anyway, struct inheritance is a tricky business. I do not think that structs should be able to inherit functions, since that makes them no different than a class, just like they are in C++. A struct should be treated specially, it should not have a virtual function table or any extra run time information like a class does. As for struct constructors, the common tactic is to use opCall, but I agree that some solution involving the 'this' keyword would be more consistent. The current solution is workable, though a bit obscure. I'm a bit uneasy about that whole l-value thing. As a design decision, it seems to violate the design principal of encapsulation. If you absolutely have to write to an object via its return value, you could try returning a pointer. The library I currently use is based on SSE, though the optimization is still incomplete. You can grab it from http://assertfalse.com -Mik |
June 13, 2006 Re: struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
Posted in reply to cschueler | cschueler skrev: > The short story is I need either > > - struct inheritance > or > - anonymous unions outside an aggregate in a mixin > > I would prefer struct inheritance: > > struct field > { > union { ... }; > union { ... }; > union { ... }; > }; > > struct vectorspace : field > { > // have anonymous unions of "field" injected into this scope } > > but I since there is no struct inheritance, I tried with mixins > > template field > { > union { ... }; > union { ... }; > union { ... }; > }; > > struct vectorspace > { > mixin field; } > > But you cannot have anonymous unions outside a struct :/( > So I'm struck at this point. Try adding an anonymous struct to the template: template field() { struct { union {...} union {...} union {...} } } > Moreover, the mixin approach is not feasible because then you cannot make field a template parameter. > > template( field ) > { > struct vectorspace > > only seem to work when field is a type, not a mixin. Try using an alias parameter: struct vectorspace(alias field) { mixin field; } > I would like to weigh in for struct inheritance, since it seems a > trivial thing to allow. C programmers have often done this by declaring a variable of the base type as the first member > of the struct. So I was a little surprised that D has no > inheritance for plain data structs. I agree that struct inheritance would be useful. > There is more missing in D that prevents me to port the > system fully: > > - explicit return by reference (return an L-value) > - struct constructors > > These are not showblockers, but missing them is ugly! I agree. Those have both been discussed several times. One common implication of not having l-value returns is: struct point { int x,y; } ... MyArray!(point) arr; ... arr[5].x = 3; // no effect > The explicit L-value return however I think is an important > concept that is missing with subtle implications. Without it, > user defined types can never be made transparent to builtin types. Consider: > > int a; > (+a) = 3; > > The unary plus operator returns an L-value, so the assignment > can take place. In C++, you can define the unary + operator > to behave the same for your type, by defining both R-value > and L-value operator: > > // R-value unary + > const mytype &operator +( const mytype &object ) > { return object; } > > // L-value unary + > mytype &operator +( mytype &object ) > { return object; } > > In D, you can only do the R-value version. Yes. This is the area where I find D most lacking. /Oskar |
June 13, 2006 Re: struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | Oskar Linde wrote:
> cschueler skrev:
>> There is more missing in D that prevents me to port the
>> system fully:
>>
>> - explicit return by reference (return an L-value)
>> - struct constructors
>>
>> These are not showblockers, but missing them is ugly!
>
>
> I agree. Those have both been discussed several times. One common implication of not having l-value returns is:
>
> struct point { int x,y; }
> ....
> MyArray!(point) arr;
> ....
> arr[5].x = 3; // no effect
>
Write MyArray.opIndex to return a pointer and it will work. I do still agree with the proposal, however.
-- Chris Nicholson-Sauls
|
June 13, 2006 Re: struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | Chris Nicholson-Sauls skrev:
> Oskar Linde wrote:
>> cschueler skrev:
>>> There is more missing in D that prevents me to port the
>>> system fully:
>>>
>>> - explicit return by reference (return an L-value)
>>> - struct constructors
>>>
>>> These are not showblockers, but missing them is ugly!
>>
>>
>> I agree. Those have both been discussed several times. One common implication of not having l-value returns is:
>>
>> struct point { int x,y; }
>> ....
>> MyArray!(point) arr;
>> ....
>> arr[5].x = 3; // no effect
>>
>
> Write MyArray.opIndex to return a pointer and it will work. I do still agree with the proposal, however.
That will work in this case, but will break the rvalue case instead:
point pt = arr[6];
/Oskar
|
June 13, 2006 Re: struct inheritance, L-value return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | On Tue, 13 Jun 2006 18:56:23 +0200, Oskar Linde <oskar.lindeREM@OVEgmail.com> wrote:
> Chris Nicholson-Sauls skrev:
>> Oskar Linde wrote:
>>> cschueler skrev:
>>>> There is more missing in D that prevents me to port the
>>>> system fully:
>>>>
>>>> - explicit return by reference (return an L-value)
>>>> - struct constructors
>>>>
>>>> These are not showblockers, but missing them is ugly!
>>>
>>>
>>> I agree. Those have both been discussed several times. One common implication of not having l-value returns is:
>>>
>>> struct point { int x,y; }
>>> ....
>>> MyArray!(point) arr;
>>> ....
>>> arr[5].x = 3; // no effect
>>>
>> Write MyArray.opIndex to return a pointer and it will work. I do still agree with the proposal, however.
>
> That will work in this case, but will break the rvalue case instead:
>
> point pt = arr[6];
point pt = *arr[6];
should work.
Regan
|
Copyright © 1999-2021 by the D Language Foundation