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