Mix struct types in the same array

Paul Backus snarwin at gmail.com
Thu Dec 19 21:26:51 UTC 2019


On Thursday, 19 December 2019 at 18:21:32 UTC, tirithen wrote:
> On Thursday, 19 December 2019 at 00:00:56 UTC, Paul Backus 
> wrote:
>>
>> interface Action
>> {
>>     void applyTo(ref User); <-- change to applyTo(T)(ref T)
>> }
>>
>> class ActionAdapter(T) : Action
>> {
>>     T payload;
>>
>>     this(T payload)
>>     {
>>         this.payload = payload;
>>     }
>>
>>     override void applyTo(ref User user) <-- change to 
>> applyTo(U)(ref U entity)
>>     {
>>         payload.applyTo(user);
>>     }
>> }
>
> Is there a way I can make the example a bit more generic even 
> by replacing the User type with a template. I tried:
>
> applyTo(ref User); <-- applyTo(T)(ref T)
> applyTo(ref User user) <-- applyTo(U)(ref U entity)
>
> It compiled but crashed with:
>
> Linking...
> /usr/bin/ld: 
> .dub/build/application-debug-linux.posix-x86_64-dmd_2089-4CFAD9B3CA5E5532C5E0608F9332C781/tryit.o: in function `_Dmain':
> .....tryit/source/app.d:55: undefined reference to 
> `_D5plant5tryit3app5Event__T7applyToTSQBjQBgQBd4UserZQzMFKQvZv'
> collect2: fel: ld returnerade avslutningsstatus 1
>
> I'm still a bit new to this language so need to practice 
> templates more, but I find D overall nice.

The reason this doesn't work is that interface methods are 
virtual, and virtual methods can't be templates. [1] If you want 
to have multiple kinds of entities, one option is to create an 
Entity interface and EntityAdapter(T) class using the same 
technique as above, and have your applyTo method accept an Entity 
as its argument. You can see an example of what that would look 
like at the following link:

https://gist.github.com/pbackus/f61734804a627d379c7916f783ea7725#file-oop_version-d

Another option is to forget about classes and interfaces and do 
everything with templates, using a library like sumtype [2]. 
Here's a link to an example of what that would look like:

https://gist.github.com/pbackus/f61734804a627d379c7916f783ea7725#file-template_version-d

Advantages of the interface + adapter version:
   + Can easily add new Actions and Entities, without changing 
existing code
   + Method dispatch is handled automatically by the compiler

Advantages of sumtype + templates version:
   + No need to allocate adapter objects on the heap

[1] https://dlang.org/spec/function.html#virtual-functions
[2] https://code.dlang.org/packages/sumtype


More information about the Digitalmars-d-learn mailing list