Re: stretto...@tutanota.com

2016-06-11 Thread ArturG via Digitalmars-d-learn

you could also use a simple wrapped cast

Ret castTo(Ret, T)(T t) if(is(T == class))
{
return cast(Ret) t;
}

then do

foo.stuff[0].castTo!Dong.x.writeln;

and if you want to guard the access you could try

foo.stuff[0].castTo!Dong.cc!((d){d.x = 5;});

cc is an alias for checkCall which is a template you can find here
http://forum.dlang.org/thread/ltalqpmpscdoziser...@forum.dlang.org,
it treats Type.init as false and ignores the call to fun.

but its not restricted to nullables only e.g.

float someF;
iota(0, someF).writeln; // normally would throw an AssertError

someF.cc!(f => iota(0, f)).writeln; // returns an empty range 
without calling iota, as float.nan is treated as false.

same as
0.0.cc!(f => iota(0, f)).writeln;


Re: stretto...@tutanota.com

2016-06-09 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 9 June 2016 at 22:19:33 UTC, Stretto wrote:

I have some class like

class bar { }
class foo : bar
{
bar[] stuff;
}

and have another class

class dong : bar
{
   int x;
}


Now sometimes stuff will contain dong's, but I cannot access 
its members it without a cast.


fooo.stuff[0].x // invalid because bar doesn't contain x;

Hence,

((cast(dong)foo.stuff[0]).x is the normal way with a possible 
type check.


But in my case I will never mix different types in stuff and 
will always use it properly or do type checking in the cases I 
might mix.




That's just the nature of working with class hierarchies. A 
Derived is always a Base, but a Base might not be a Derived. If 
your Bar array in Foo will always hold only one type of Bar, then 
you can parameterize Foo with a type:


###
class Bar { }

// Only accept types that are implicitly convertible to Bar
class Foo(T : Bar) : Bar
{
T[] stuff;
}

class Dong : Bar
{
   int x;
   this(int x) { this.x = x; }
}

void main()
{
import std.stdio;
auto foo = new Foo!Dong();
foo.stuff ~= new Dong(10);
writeln(foo.stuff[0].x);
}

###

Another option is to use a parameterized getter, which is 
somewhat cleaner than a cast.


###
class Foo : Bar
{
Bar[] stuff;
T get(T : Bar)(size_t index)
{
return cast(T)stuff[index];
}
}

void main()
{
import std.stdio;
auto foo = new Foo();
foo.stuff ~= new Dong(10);
writeln(foo.get!Dong(0).x);
}

###


Re: stretto...@tutanota.com

2016-06-09 Thread Stretto via Digitalmars-d-learn

Ultimately what I want to do is access a member

foo.Dongs[i];

Where Dongs is essentially a "view" in to the Bars array and only 
accesses types of type Dong.


It seems one can't do both an override on a name("Dongs") and an 
index on the overridden name(`[i]`)?


It is not appropriate to use foo.Dongs(i).

A clear example:

https://dpaste.dzfl.pl/7ea52a0f21ce




stretto...@tutanota.com

2016-06-09 Thread Stretto via Digitalmars-d-learn

I have some class like

class bar { }
class foo : bar
{
bar[] stuff;
}

and have another class

class dong : bar
{
   int x;
}


Now sometimes stuff will contain dong's, but I cannot access its 
members it without a cast.


fooo.stuff[0].x // invalid because bar doesn't contain x;

Hence,

((cast(dong)foo.stuff[0]).x is the normal way with a possible 
type check.


But in my case I will never mix different types in stuff and will 
always use it properly or do type checking in the cases I might 
mix.


Rather than add a dong[] dongs; to foo, which increases the size 
of foo and wastes memory just to prevent the cast, I'm curious if 
there is any other way to solve this problem?


I simply want to do foo.stuff[0].x and have foo.stuff[0] be 
treated as an image.


Is an opDispatch and/or opIndex required or is there some alias 
trick that can be used?


I'd rather access like foo.dongs[0].x without defining a dong 
array directly in foo, but simply alias to stuff with an implicit 
cast to dong.