Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-15 Thread Jacob Carlborg via Digitalmars-d-learn

On 2015-07-14 17:53, Rene Zwanenburg wrote:


Sure, but that would make Base!Derived and Base!AnotherSubClass
different types.

What I'd like to end up with is a Base[], being able to call foo() on
the array members. Other parts of the code will add instances of derived
types to this array, and have set the callback function to a delegate
accepting said derived type.


You can add another base type that is not templated:

abstract class Base
{
abstract void foo ();
}

abstract class TemplateBase(T) : Base
{
alias CallbackType = void delegate(T);

CallbackType callback;

override void foo ()
{
callback(cast(T) this);
}
}

class Derived : TemplateBase!(Derived)
{
void derivedFunc()
{
import std.stdio;
writeln("Derived object in action...");
}
}

void main()
{
auto d = new Derived();
d.callback = (Derived d) { d.derivedFunc(); };
Base[] bases = [d];
foreach (b ; bases)
b.foo();
}

--
/Jacob Carlborg


Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-15 Thread Ali Çehreli via Digitalmars-d-learn

On 07/14/2015 08:28 AM, Rene Zwanenburg wrote:

> But the CallbackType should be able to prevent such unsafe assignments.

The following struct applies what others have recommended only if an 
actual derived type is provided. However, it is still unsafe as the 
direct assignment to 'callback' cannot know that the object is the same 
as template parameter D.


struct CallbackBased(B)
{
alias Func = void delegate(B);
Func func;

void opAssign(D)(void delegate(D) arg)
if (is (D : B))
{
func = cast(Func)(arg);
}

void opCall(B obj)
{
func(obj);
}
}

class Base
{
alias CallbackType = CallbackBased!Base;

CallbackType callback;

void foo()
{
callback(this);
}
}

class Derived : Base
{
void derivedFunc()
{
import std.stdio;
writeln("Derived object in action...");
}
}

void main()
{
auto d = new Derived();
d.callback = (Derived d) { d.derivedFunc(); };
d.foo();
}

Ali



Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Jacob Carlborg via Digitalmars-d-learn

On 2015-07-14 17:28, Rene Zwanenburg wrote:

Given the following code:

class Base
{
 alias CallbackType = void delegate(Base);

 CallbackType callback;

 void foo()
 {
 callback(this);
 }
}

class Derived : Base
{

}

void main()
{
 auto d = new Derived();
 d.callback = (Derived d) { /* Do something */ }
}

Obviously this won't compile, since the callback function needs to have
Base as parameter, not Derived.


You can cast the delegate. It's probably unsafe but a simple example works.

--
/Jacob Carlborg


Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Rene Zwanenburg via Digitalmars-d-learn
On Tuesday, 14 July 2015 at 17:26:32 UTC, Steven Schveighoffer 
wrote:

On 7/14/15 11:28 AM, Rene Zwanenburg wrote:

Given the following code:

class Base
{
 alias CallbackType = void delegate(Base);

 CallbackType callback;

 void foo()
 {
 callback(this);
 }
}

class Derived : Base
{

}

void main()
{
 auto d = new Derived();
 d.callback = (Derived d) { /* Do something */ }
}

Obviously this won't compile, since the callback function 
needs to have
Base as parameter, not Derived. But the given code is 
perfectly safe
because in main d typed as Derived, not Base. Does anyone know 
a clean
way to support the code given in main(), preferably by 
defining some

smart CallbackType so Derived doesn't need to be modified?


No, this isn't possible. Only thing you can do is:

d.callback = (Base b) { if(auto d = cast(Derived)b) { /* Do 
something */ } else assert(0); };


-Steve


Thanks, I'll have to think of something else then.

At my day job I mostly work with C#, and I strongly dislike how 
event handler parameters there have to be broader-typed (is that 
even a valid term?) than they logically need to be, which is why 
I'm trying to avoid doing something similar here.


Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/14/15 11:28 AM, Rene Zwanenburg wrote:

Given the following code:

class Base
{
 alias CallbackType = void delegate(Base);

 CallbackType callback;

 void foo()
 {
 callback(this);
 }
}

class Derived : Base
{

}

void main()
{
 auto d = new Derived();
 d.callback = (Derived d) { /* Do something */ }
}

Obviously this won't compile, since the callback function needs to have
Base as parameter, not Derived. But the given code is perfectly safe
because in main d typed as Derived, not Base. Does anyone know a clean
way to support the code given in main(), preferably by defining some
smart CallbackType so Derived doesn't need to be modified?


No, this isn't possible. Only thing you can do is:

d.callback = (Base b) { if(auto d = cast(Derived)b) { /* Do something */ 
} else assert(0); };


-Steve


Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Rene Zwanenburg via Digitalmars-d-learn

On Tuesday, 14 July 2015 at 15:35:04 UTC, Kagamin wrote:

Template Base on Derived:

class Derived : Base!Derived
{

}


Sure, but that would make Base!Derived and Base!AnotherSubClass 
different types.


What I'd like to end up with is a Base[], being able to call 
foo() on the array members. Other parts of the code will add 
instances of derived types to this array, and have set the 
callback function to a delegate accepting said derived type.


This is part of a library I'm working on. I don't mind if the 
library itself contains some nastiness to get this to work, as 
long as user code, which defines the derived types, is type safe 
and clean.


Re: Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Kagamin via Digitalmars-d-learn

Template Base on Derived:

class Derived : Base!Derived
{

}


Covariant callback functions, or assigning base class members through a subclass reference

2015-07-14 Thread Rene Zwanenburg via Digitalmars-d-learn

Given the following code:

class Base
{
alias CallbackType = void delegate(Base);

CallbackType callback;

void foo()
{
callback(this);
}
}

class Derived : Base
{

}

void main()
{
auto d = new Derived();
d.callback = (Derived d) { /* Do something */ }
}

Obviously this won't compile, since the callback function needs 
to have Base as parameter, not Derived. But the given code is 
perfectly safe because in main d typed as Derived, not Base. Does 
anyone know a clean way to support the code given in main(), 
preferably by defining some smart CallbackType so Derived doesn't 
need to be modified?


I understand this is unsafe in other scenarios, for example:

class AnotherSubClass : Base
{

}

void bar(Base b1, Base b2)
{
b1.callback = b2.callback;
}

void doom()
{
auto b1 = new Derived();
auto b2 = new AnotherSubClass();
b2.callback = (AnotherSubClass a) { };
bar(b1, b2);
}

But the CallbackType should be able to prevent such unsafe 
assignments.