| 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
 
Permalink
Reply