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

Meta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Nov 8 05:51:15 PST 2015


On Sunday, 8 November 2015 at 10:31:13 UTC, Panke 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?

The issue is because your delegate inside Leaf returns a T by 
value, and T in this case is
the type std.variant.This; it's an opaque struct type to allow 
for recursive structures. If it sees This* or This[] in the 
template argument list to Algebraic, it'll do some magic to 
replace this with another Variant. That magic is 
std.typecons.ReplaceType[1]. However, note the warning on 
ReplaceType:

"However, member types in `struct`s or `class`es are not replaced 
because there
are no ways to express the types resulting after replacement."

And thus it can't replace the T return type of your delegate with 
the proper type. The compiler sees that you're trying to return 
the opaque struct This by value and violently disagrees with that 
notion, refusing to compile. To make that particular compiler 
error go away you can change the return type of the delegate to 
T* or T[], but that's not particularly useful as you're still 
just returning a pointer to This, not the recursive type. I'm not 
completely sure what you're trying to do is possible in D, and 
definitely not without enhancements to ReplaceType.


1. 
https://github.com/D-Programming-Language/phobos/blob/245c7ab0b591cb48b3dbb239640dd54e0717110a/std/typecons.d#L6643


More information about the Digitalmars-d-learn mailing list