std.variant.Algebraic, self referential types and delegate members

Panke via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Nov 8 03:44:02 PST 2015


On Sunday, 8 November 2015 at 11:28:05 UTC, Jonathan M Davis 
wrote:
> On Sunday, November 08, 2015 10:31:11 Panke via 
> Digitalmars-d-learn wrote:
>> import std.variant, std.stdio;
>>
>> ---
>> struct NodeTypeA(T) { T[] children; }
>> struct NodeTypeB(T) { Tree children; }
>> struct Leaf(T) { T delegate() dg; }
>>
>> alias Tree = Algebraic!(Leaf, NodeTypeA!This, NodeTypeB!This);
>>
>> void main()
>> {
>>    Tree t;
>> }
>> ---
>>
>> yields
>>
>> tmp.d(6): Error: functions cannot return opaque type This by 
>> value
>> tmp.d(8): Error: template instance tmp.Leaf!(This) error
>> instantiating
>>
>> This limitation seems arbitrary to me. What's the reason here?
>
> Okay. Several things here. For starters, NodeTypeA, NodeTypeB, 
> and Leaf are not actually types. They're templates for types. 
> If you want a type, you have to instantiate them. So, something 
> like Algebraic!Leaf doesn't make any sense. You need an 
> instantiation of Leaf - e.g. Algebraic!(Leaf!int) - rather than 
> just Leaf.

My failure, I've played with the code while crafting the post. 
I've used
---
alias Tree = Algebraic!(Leaf!This, NoteTypeA!This, NoteTypeB!This)
---

So no templates, just types.

> Next, you have a recursive template instantiation going on 
> here. Tree depends on knowing what a NodeTypeB looks like, 
> because it's using it in its instantiation of Algebraic. 
> Algebraic!(Foo, Bar) is told to hold either a Foo or a Bar, 
> which means that it needs to know their definitions - not just 
> their names. You need to be using pointers if you want to be 
> able to avoid having to know the actual definition of the type. 
> So, when you tell NodeTypeB to hold a Tree when a Tree holds a 
> NodeTypeB, it's impossible to figure out what the actual layout 
> of those types. You have a recursive expansion.
>
> If you want to have a recursive type definition, you _must_ use 
> pointers so that the actual definition of the type is not 
> required.

Thing is that delegate is nothing more than a glorified pair of 
pointers.

> Also, I have no idea what the deal with the This in your code 
> is. IIRC, there's a feature involving This with template 
> definitions, but you're just using it outside of a template 
> definition, so I don't know if that's legal.

It's a recent feature of Algebraic to allow recursive 
definitions. I'd assume that it uses pointers under the hood.

Older compiler but same error message: http://goo.gl/P0wmqe


More information about the Digitalmars-d-learn mailing list