Re: Why does this code only work with `std.conv.to` whilst not with `cast`?

2023-01-08 Thread matheus via Digitalmars-d-learn

On Sunday, 8 January 2023 at 12:39:37 UTC, thebluepandabear wrote:

...
The `foreach` worked for that case since `bark` is a method of 
`IDog`. `update` is not so a conversion to `Button[]` is needed.




In that case, you could do a casting like this:

import std.stdio, std.conv;

interface IDog {
void bark();
}

class Dog: IDog{
string s;
this(string _s){s = _s;}
void bark(){writeln(s);}
void update(string _s){ s ~= " - " ~ _s; }
}

class List{
IDog[] dogs;
void add(T)(T d){ dogs ~= d;  }
}

void main(){
auto d1 = new Dog("meaw!");
auto d2 = new Dog("wof!");
auto l = new List();
l.add(d1);
l.add(d2);

foreach(i,d; l.dogs){ // I'm using 'i' just to show each 
update.

(cast(Dog)d).update(to!string(i));
d.bark();
}
}

Prints:

meaw! - 0
wof! - 1

Matheus.


Re: Why does this code only work with `std.conv.to` whilst not with `cast`?

2023-01-08 Thread matheus via Digitalmars-d-learn

On Sunday, 8 January 2023 at 11:29:10 UTC, thebluepandabear wrote:

...


There is an explanation here: 
https://forum.dlang.org/post/tqukutfzeaxedunuv...@forum.dlang.org


But in any case I'd like to point it out that I think you could 
do that foreach without casting or std.conv by just omitting the 
type of the variable you're iterating:


import std.stdio, std.conv;

interface IDog {
void bark();
}

class Dog: IDog{
string s;
this(string _s){s = _s;}
void bark(){writeln(s);}
}

class List{
IDog[] dogs;
void add(T)(T d){ dogs ~= d;  }
}

void main(){
auto d1 = new Dog("meaw!");
auto d2 = new Dog("wof!");
auto l = new List();
l.add(d1);
l.add(d2);

foreach(d; l.dogs){ // No type informed for "d"
d.bark();
}
}

Prints:

meaw!
wof!

Matheus.


Re: Why does this code only work with `std.conv.to` whilst not with `cast`?

2023-01-08 Thread thebluepandabear via Digitalmars-d-learn

On Sunday, 8 January 2023 at 12:35:38 UTC, matheus wrote:
On Sunday, 8 January 2023 at 11:29:10 UTC, thebluepandabear 
wrote:

...


There is an explanation here: 
https://forum.dlang.org/post/tqukutfzeaxedunuv...@forum.dlang.org


But in any case I'd like to point it out that I think you could 
do that foreach without casting or std.conv by just omitting 
the type of the variable you're iterating:


import std.stdio, std.conv;

interface IDog {
void bark();
}

class Dog: IDog{
string s;
this(string _s){s = _s;}
void bark(){writeln(s);}
}

class List{
IDog[] dogs;
void add(T)(T d){ dogs ~= d;  }
}

void main(){
auto d1 = new Dog("meaw!");
auto d2 = new Dog("wof!");
auto l = new List();
l.add(d1);
l.add(d2);

foreach(d; l.dogs){ // No type informed for "d"
d.bark();
}
}

Prints:

meaw!
wof!

Matheus.


The `foreach` worked for that case since `bark` is a method of 
`IDog`. `update` is not so a conversion to `Button[]` is needed.


I will look at your resource, thanks.


Re: Why does this code only work with `std.conv.to` whilst not with `cast`?

2023-01-08 Thread ag0aep6g via Digitalmars-d-learn

On 08.01.23 12:29, thebluepandabear wrote:

```D
interface ICustomDrawable {
     void render(sfRenderWindow* renderWindow);
}

[...]> class Button : ICustomDrawable {
[...]

}

[...]

class StackLayout : ICustomDrawable {

[...]

     ICustomDrawable[] _children;
}
```

For some reason, when I want to cast the `children` (property), only the 
second example works:


1.

```D
foreach (Button button; cast(Button[])(_boardSizeRow.children)) {
     button.update(event, _renderWindow);
}
```

2.

```D
foreach (Button button; to!(Button[])(_boardSizeRow.children)) {
     button.update(event, _renderWindow);
}
```


Two things you need to know:

1. While an interface reference implicitly converts to a compatible 
class reference, the resulting pointer is slightly different.



interface I {}
class C : I {}
void main()
{
C c = new C;
I i = c;
import std.stdio;
writeln(cast(void*) c); /* e.g. 7F3C140A7000 */
writeln(cast(void*) i); /* e.g. 7F3C140A7010 */
}


2. Casting from one array type to another is done "as a type paint"[1]. 
The elements of the array are reinterpreted, not converted.


But reinterpreting interface references as class references won't work, 
because the pointers will be wrong. You need to convert each element of 
the array (which is what `to` does).



[1] https://dlang.org/spec/expression.html#cast_array


Why does this code only work with `std.conv.to` whilst not with `cast`?

2023-01-08 Thread thebluepandabear via Digitalmars-d-learn
I've been writing some code and I have been experimenting with 
casting. I've found that sometimes only `std.conv.to!` does the 
job over casting, and I am unsure why this is the case as I 
assumed that they are both the same.


I have the following interface:

```D
interface ICustomDrawable {
void render(sfRenderWindow* renderWindow);
}
```

And the following class that implements that interface:

```D
class Button : ICustomDrawable {
...
override void render(sfRenderWindow* renderWindow) {
...
}
}
```

And this class which uses `ICustomDrawable`:

```D
class StackLayout : ICustomDrawable {
   ...
void addChild(T)(T child) {
static assert(is(T : ICustomDrawable), "Invalid type T 
for child");

...
}
...
ICustomDrawable[] _children;
}
```

For some reason, when I want to cast the `children` (property), 
only the second example works:


1.

```D
foreach (Button button; cast(Button[])(_boardSizeRow.children)) {
button.update(event, _renderWindow);
}
```

2.

```D
foreach (Button button; to!(Button[])(_boardSizeRow.children)) {
button.update(event, _renderWindow);
}
```

When I run the first code example I get a black screen, whilst 
with the second I do not. I find this very strange as when I 
write to the console the 'type', it is the same for both 
scenarios.


Help would be appreciated as to why this is happening so I can 
better understand how D works.