## digitalmars.D.learn - Struct "inheritance"

Vidar Wahlberg <canidae exent.net> writes:
```Good day.

I know "inheritance" is a misleading word as there's no such thing when
it comes to structs, but I couldn't think of a better description for
this problem:

Let's say I got a struct for a location on a 2-dimensional plane:
struct Point {
int x;
int y;
}
Further I also need to represent a location in a 3-dimensional space:
struct Coordinate {
int x;
int y;
int z;
}
If these were classes instead I could simply make Coordinate inherit
from Point and only add "int z;". This would also make the thing I'm
trying to achieve much easier; Consider I have a method that does
something nifty with "x" and "y", I'd like this method to handle both
"Point" and "Coordinate", if they were classes it would be fairly simple:
int somethingNifty(Point p) {
return p.x + p.y;
}

So why not just use classes? I've understood it as there may be a
performance gain by using structs over classes, and in my program Point
and Coordinate are used heavily.

Obviously I'm fairly new to both D and structs, I have plenty Java and
some C++ experience (I've avoided using structs in C++) and I have "The
D Programming Language" book by Andrei which I'm happy to look up in,
although I've failed to find an answer to this question in the book, in
this newsgroup and on the net.
I would greatly appreciate if someone could give me a nudge the the
right direction.
```
Feb 04 2012
Trass3r <un known.com> writes:
``` So why not just use classes? I've understood it as there may be a
performance gain by using structs over classes, and in my program Point
and Coordinate are used heavily.

The other big difference is value vs. reference type.
You can use alias this to achieve something like "struct inheritance".
```
Feb 04 2012
=?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
```On Sat, 04 Feb 2012 12:38:30 +0100, Vidar Wahlberg <canidae exent.net>
wrote:

Good day.

I know "inheritance" is a misleading word as there's no such thing when
it comes to structs, but I couldn't think of a better description for
this problem:

Let's say I got a struct for a location on a 2-dimensional plane:
struct Point {
int x;
int y;
}
Further I also need to represent a location in a 3-dimensional space:
struct Coordinate {
int x;
int y;
int z;
}
If these were classes instead I could simply make Coordinate inherit
from Point and only add "int z;". This would also make the thing I'm
trying to achieve much easier; Consider I have a method that does
something nifty with "x" and "y", I'd like this method to handle both
"Point" and "Coordinate", if they were classes it would be fairly simple:
int somethingNifty(Point p) {
return p.x + p.y;
}

So why not just use classes? I've understood it as there may be a
performance gain by using structs over classes, and in my program Point
and Coordinate are used heavily.

Obviously I'm fairly new to both D and structs, I have plenty Java and
some C++ experience (I've avoided using structs in C++) and I have "The
D Programming Language" book by Andrei which I'm happy to look up in,
although I've failed to find an answer to this question in the book, in
this newsgroup and on the net.
I would greatly appreciate if someone could give me a nudge the the
right direction.

It seems that what you want is alias this:

struct Point {
int x;
int y;
}

struct Coordinate {
Point pt;
int z;
alias pt this;
}

void foo( Point p ) {}

void main( ) {
Coordinate c;
foo( c );
c.x = 3;
c.y = 4;
c.z = 5;
}
```
Feb 04 2012
Vidar Wahlberg <canidae exent.net> writes:
```On 2012-02-04 13:06, Simen Kjærås wrote:
It seems that what you want is alias this:

Thank you both, that's exactly what I needed.

Leeching a bit more on the thread:
Going back to the method:
int somethingNifty(Point p) {
return p.x + p.y;
}

Let's say I have the following code:
for (x; 0 .. 10) {
for (y; 0 .. 10) {
Point p = {x, y};
somethingNifty(p);
}
}

[How] can you rewrite those two statements inside the loops to a single
line? For example (this doesn't work):
somethingNifty(Point(x, y));

"Coordinate" ("Point" is similar in structure):
import Point;
struct Coordinate {
Point _point;
int _z;
property auto point() const {
return _point;
}
property auto point(Point point) {
return _point = point;
}
property auto z() const {
return _z;
}
property auto z(int z) {
return _z = z;
}
bool opEquals(ref const Coordinate c) const {
return z == c.z && point == c.point;
}
}

Compilation fails with the following error:
Coordinate.d:18: Error: function Point.Point.opEquals (ref const
const(Point) p) const is not callable using argument types
(const(Point)) const
Coordinate.d:18: Error: c.point() is not an lvalue

Noteworthy the code compiles fine if i replace "point" and "c.point"
with "_point" and "c._point", but then I'm referencing _point directly
instead of through the property "point" (which may do something else
than just return _point in the future).
I've looked at
and that page is slightly confusing. It claims that:
If structs declare an opEquals member function, it should follow the
following form:
struct S {
int opEquals(ref const S s) { ... }
}

However, I can't even get the code to compile if I do that, the compiler
(gdc-4.6) says:
Error: function Coordinate.Coordinate.opEquals type signature should be
const bool(ref const(Coordinate)) not int(ref const const(Coordinate) c)

I hope it's somewhat clear what I'm trying to achieve.
```
Feb 04 2012
bearophile <bearophileHUGS lycos.com> writes:
```Vidar Wahlberg:

Leeching a bit more on the thread:
Going back to the method:
int somethingNifty(Point p) {
return p.x + p.y;
}

Let's say I have the following code:
for (x; 0 .. 10) {
for (y; 0 .. 10) {
Point p = {x, y};
somethingNifty(p);
}
}

[How] can you rewrite those two statements inside the loops to a single
line? For example (this doesn't work):
somethingNifty(Point(x, y));

This works:

struct Point {
int x, y;
}

int somethingNifty(Point p) {
return p.x + p.y;
}

void main( ) {
foreach (x; 0 .. 10)
foreach (y; 0 .. 10)
somethingNifty(Point(x, y));
}

Bye,
bearophile
```
Feb 04 2012
=?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
```On Sat, 04 Feb 2012 13:55:55 +0100, Vidar Wahlberg <canidae exent.net>  =

wrote:

On 2012-02-04 13:06, Simen Kj=C3=A6r=C3=A5s wrote:
It seems that what you want is alias this:

Thank you both, that's exactly what I needed.

Leeching a bit more on the thread:
Going back to the method:
int somethingNifty(Point p) {
return p.x + p.y;
}

Let's say I have the following code:
for (x; 0 .. 10) {
for (y; 0 .. 10) {
Point p =3D {x, y};
somethingNifty(p);
}
}

[How] can you rewrite those two statements inside the loops to a singl=

e  =

line? For example (this doesn't work):
somethingNifty(Point(x, y));

Like bearophile said, Point(x, y) should work - assuming you have
defined no other constructors for Point.

You can also explicitly define a constructor that does what you want.

=

"Coordinate" ("Point" is similar in structure):
import Point;
struct Coordinate {
Point _point;
int _z;
property auto point() const {
return _point;
}
property auto point(Point point) {
return _point =3D point;
}
property auto z() const {
return _z;
}
property auto z(int z) {
return _z =3D z;
}
bool opEquals(ref const Coordinate c) const {
return z =3D=3D c.z && point =3D=3D c.point;
}
}

Compilation fails with the following error:
Coordinate.d:18: Error: function Point.Point.opEquals (ref const  =

const(Point) p) const is not callable using argument types  =

(const(Point)) const
Coordinate.d:18: Error: c.point() is not an lvalue

Noteworthy the code compiles fine if i replace "point" and "c.point"  =

with "_point" and "c._point", but then I'm referencing _point directly=

=

instead of through the property "point" (which may do something else  =

than just return _point in the future).
I've looked at  =

=

and that page is slightly confusing. It claims that:
If structs declare an opEquals member function, it should follow the  =

following form:
struct S {
int opEquals(ref const S s) { ... }
}

However, I can't even get the code to compile if I do that, the compil=

er  =

(gdc-4.6) says:
Error: function Coordinate.Coordinate.opEquals type signature should b=

e  =

const bool(ref const(Coordinate)) not int(ref const const(Coordinate) =

c)
I hope it's somewhat clear what I'm trying to achieve.

It is. The problem is that bool opEquals(ref const Point) expects a Poin=
t
by reference, and the return value from your property is a temporary, fr=
om
which we can get no reference. The solution is to remove the ref:
bool opEquals(const Point). The only reason to use ref here is to cut do=
wn
on copying, and might be worthwhile on larger structures.
```
Feb 04 2012
Vidar Wahlberg <canidae exent.net> writes:
```On 2012-02-04 14:45, Simen Kjærås wrote:
Like bearophile said, Point(x, y) should work - assuming you have
defined no other constructors for Point.

You are correct, my apologies for not testing more thoroughly.
Let me try again, explaining the real issue:
I have 3 files:
-- Bar.d --
import Foo;
import Struct;
class Bar {
Foo _foo;
this() {
_foo = new Foo(Struct(1));
}
}
void main() {
new Bar();
}

-- Foo.d --
import Struct;
class Foo {
Struct _s;
this(Struct s) {
_s = s;
}
}

-- Struct.d --
struct Struct {
int baz;
}

This code does not compile:
Bar.d:6: Error: function expected before (), not module Struct of type void
Bar.d:6: Error: constructor Foo.Foo.this (Struct s) is not callable
using argument types (_error_)

Why is that?

It is. The problem is that bool opEquals(ref const Point) expects a Point
by reference, and the return value from your property is a temporary, from
which we can get no reference. The solution is to remove the ref:
bool opEquals(const Point). The only reason to use ref here is to cut down
on copying, and might be worthwhile on larger structures.

I've tried removing the "ref", but I get other errors in return then:
Point.d:19: Error: function Point.Point.opEquals type signature should
be const bool(ref const(Point)) not const bool(const const(Point) p)
Coordinate.d:20: Error: function Coordinate.Coordinate.opEquals type
signature should be const bool(ref const(Coordinate)) not const
bool(const const(Coordinate) c)
```
Feb 04 2012
=?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
```On Sat, 04 Feb 2012 15:04:50 +0100, Vidar Wahlberg <canidae exent.net>
wrote:

This code does not compile:
Bar.d:6: Error: function expected before (), not module Struct of type
void
Bar.d:6: Error: constructor Foo.Foo.this (Struct s) is not callable
using argument types (_error_)

Why is that?

I see. There's a hint in the error message: "function expected [...],
not module". Struct is the name of a module, so the compiler thinks
you want to access something inside it. If you want 'Struct' to refer
to the type, you must use selective import[1]:

import Struct : Struct;

This says 'I want only the type Struct from the module Struct, not
everything else in there.'

The other solution is to simply use different names for the type and
the module.

It is. The problem is that bool opEquals(ref const Point) expects a
Point
by reference, and the return value from your property is a temporary,
from
which we can get no reference. The solution is to remove the ref:
bool opEquals(const Point). The only reason to use ref here is to cut
down
on copying, and might be worthwhile on larger structures.

I've tried removing the "ref", but I get other errors in return then:
Point.d:19: Error: function Point.Point.opEquals type signature should
be const bool(ref const(Point)) not const bool(const const(Point) p)
Coordinate.d:20: Error: function Coordinate.Coordinate.opEquals type
signature should be const bool(ref const(Coordinate)) not const
bool(const const(Coordinate) c)

I cannot seem to recreate this error message. Which version of the
compiler are you using?

[1]: http://www.d-programming-language.org/module.html#ImportDeclaration
```
Feb 04 2012
Vidar Wahlberg <canidae exent.net> writes:
```Sending this again, got an error the first time and it appears like it
was not sent.

On 2012-02-04 21:48, Simen Kjærås wrote:
I see. There's a hint in the error message: "function expected [...],
not module". Struct is the name of a module, so the compiler thinks
you want to access something inside it. If you want 'Struct' to refer
to the type, you must use selective import[1]:

import Struct : Struct;

I see, thanks, that does solve the problem. It is slightly confusing
that you don't get this kind of error for "Foo" in "Bar.d", though
(compiler seems to understand that I mean the class "Foo" rather than
the module "Foo" in this code: "_foo = new Foo(Struct(1))").

Also, is this really ambiguous? Are there any cases where you can have a
module name followed by a parentheses, i.e. "<module>("?

I cannot seem to recreate this error message. Which version of the
compiler are you using?

I'm using gdc-4.6 (Debian 4.6.2-4).
Using the Struct from above I can easily recreate the error:
struct Struct {
int baz;
bool opEquals(const Struct s) const {
return baz == s.baz;
}
}
```
Feb 05 2012
=?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
```On Sun, 05 Feb 2012 11:58:40 +0100, Vidar Wahlberg <canidae exent.net>
wrote:

Also, is this really ambiguous? Are there any cases where you can have a
module name followed by a parentheses, i.e. "<module>("?

Not that I know.

> I cannot seem to recreate this error message. Which version of the
> compiler are you using?

I'm using gdc-4.6 (Debian 4.6.2-4).
Using the Struct from above I can easily recreate the error:
struct Struct {
int baz;
bool opEquals(const Struct s) const {
return baz == s.baz;
}
}

Ah. That's the equivalent of DMD 2.054. I don't have that installed, but
it may be that this feature was not added until after that.

Workaround: Use a templated opEquals:

struct Struct {
int baz;
bool opEquals()(const Struct s) const {
return baz == s.baz;
}
}

Hope this works.
```
Feb 05 2012
Vidar Wahlberg <canidae exent.net> writes:
```On 2012-02-05 14:16, Simen Kjærås wrote:
On Sun, 05 Feb 2012 11:58:40 +0100, Vidar Wahlberg <canidae exent.net>
wrote:
Also, is this really ambiguous? Are there any cases where you can have
a module name followed by a parentheses, i.e. "<module>("?

Not that I know.

Possibly something that could make the language slightly more newbie
friendly here, then. For now I'll just keep the filenames in lowercase
so i "import struct;" rather than "import Struct;" (I see the norm for D
is to keep the filenames in lowercase, might as well follow it).

It appears like it ignores "module <name>;" and always use the filename
for module name (or I've misunderstood what "module" is used for). If I
create a file "Foo.d" which contains "module foo;", then in any other
file I wish to include module "foo" in I must write "include Foo;", not
"include foo;".

I'm using gdc-4.6 (Debian 4.6.2-4).

Ah. That's the equivalent of DMD 2.054. I don't have that installed, but
it may be that this feature was not added until after that.

I'm running GDC 4.6.2, not 4.6.0 (I just pasted output from "gdc-4.6

Workaround: Use a templated opEquals:

struct Struct {
int baz;
bool opEquals()(const Struct s) const {
return baz == s.baz;
}
}

Hope this works.

Yes, it does. I have to read a bit about templating as I don't
understand exactly what that "()" means, but it did solve my problem,
thanks!
```
Feb 05 2012
"Daniel Murphy" <yebblies nospamgmail.com> writes:
```"Vidar Wahlberg" <canidae exent.net> wrote in message
news:jgm2qk\$c2g\$1 digitalmars.com...
It appears like it ignores "module <name>;" and always use the filename
for module name (or I've misunderstood what "module" is used for). If I
create a file "Foo.d" which contains "module foo;", then in any other file
I wish to include module "foo" in I must write "include Foo;", not
"include foo;".

The names only need to match if the compiler/build tool has to find the
module itself.  If you call the compiler with all modules listed:
gdc bar.d Foo.d etc.d
then it should be able to work it out.  (This is how it works with dmd,
anyway.  GDC is probably the same)
```
Feb 05 2012
Vidar Wahlberg <canidae exent.net> writes:
```On 2012-02-05 15:19, Daniel Murphy wrote:
The names only need to match if the compiler/build tool has to find the
module itself.  If you call the compiler with all modules listed:
gdc bar.d Foo.d etc.d
then it should be able to work it out.  (This is how it works with dmd,
anyway.  GDC is probably the same)

Actually, that is what I do. GDC does not seem to figure it out:
naushika:~/tmp> cat Foo.d
module foo;
...
naushika:~/tmp> gdc-4.6 bar.d Foo.d baz.d
bar.d:2: Error: module foo is in file 'foo.d' which cannot be read
import path[0] = /usr/include/d2/4.6/x86_64-linux-gnu
import path[1] = /usr/include/d2/4.6
naushika:~/tmp> mv Foo.d foo.d
naushika:~/tmp> gdc-4.6 bar.d foo.d baz.d
naushika:~/tmp>
```
Feb 05 2012
"Daniel Murphy" <yebblies nospamgmail.com> writes:
```I guess you've found a bug then. :)

"Vidar Wahlberg" <canidae exent.net> wrote in message
news:jgm7sh\$k4u\$1 digitalmars.com...
On 2012-02-05 15:19, Daniel Murphy wrote:
The names only need to match if the compiler/build tool has to find the
module itself.  If you call the compiler with all modules listed:
gdc bar.d Foo.d etc.d
then it should be able to work it out.  (This is how it works with dmd,
anyway.  GDC is probably the same)

Actually, that is what I do. GDC does not seem to figure it out:
naushika:~/tmp> cat Foo.d
module foo;
...
naushika:~/tmp> gdc-4.6 bar.d Foo.d baz.d
bar.d:2: Error: module foo is in file 'foo.d' which cannot be read
import path[0] = /usr/include/d2/4.6/x86_64-linux-gnu
import path[1] = /usr/include/d2/4.6
naushika:~/tmp> mv Foo.d foo.d
naushika:~/tmp> gdc-4.6 bar.d foo.d baz.d
naushika:~/tmp>

```
Feb 05 2012
=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
```On 02/04/2012 03:38 AM, Vidar Wahlberg wrote:

Let's say I got a struct for a location on a 2-dimensional plane:
struct Point {
int x;
int y;
}
Further I also need to represent a location in a 3-dimensional space:
struct Coordinate {
int x;
int y;
int z;
}
If these were classes instead I could simply make Coordinate inherit
from Point and only add "int z;".

There is also template mixins to inject complete features into the code
(similar to C macros but without their gotchas).

The following templatizes the coordinate types, but you could use put
write everywhere:

import std.stdio;

template Point2D(T)
{
T x;
T y;

void foo2D()
{
writefln("Using (%s,%s)", x, y);
}
}

struct Coordinate(T)
{
mixin Point2D!T;   // <-- Inject x, y, and foo2D() here
T z;

this(T x, T y, T z)
{
this.x = x;
this.y = y;
this.z = z;
}
}

void main()
{
auto c = Coordinate!double(1.1, 2.2, 3.3);
c.foo2D();
}

You could insert the following line in any other scope and you would
have x, y, foo2D() inserted right there as well:

if (someCondition) {
mixin Point2D!T;   // <-- Inject x, y, and foo2D() here

// ... use the local x, y, and foo2D() here
}

Of course 'static if' may be even more suitable in other cases.

Ali
```
Feb 04 2012
=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
```On 02/04/2012 08:25 AM, Ali Çehreli wrote:
The following templatizes the coordinate types, but you could use put
write everywhere:

That should be "... you could write *ints* everywhere".

Ali
```
Feb 04 2012