Cannot use std.array.Appender in recursive types

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Aug 9 12:00:54 PDT 2017


On 8/9/17 2:25 PM, Nordlöw wrote:
> Why doesn't appending to `subs` work with std.array.Appender in
> 
>      struct T
>      {
>          string src;
>          import std.array : Appender;
>          Appender!(T[]) subs;
>      }
>      T t;
>      t.subs ~= T.init; // ERRORS
>      t.subs.put(T.init); // ERRORS
> 
> when it works with builtin arrays as in
> 
>      struct S
>      {
>          string src;
>          S[] subs;
>      }
>      S s;
>      s.subs ~= S.init;
> 
> ?
> 
> Specifically
> 
>      t.subs ~= T.init
> 
> errors as
> 
>      Error: cannot append type T to type Appender!(T[])

Here is the problem:

ElementType!(T[]) is void.

Here is ElementType:
template ElementType(R)
{
     static if (is(typeof(R.init.front.init) T))
         alias ElementType = T;
     else
         alias ElementType = void;
}

So what is happening here (I think), is that T isn't fully defined, so 
T.init.front.init is an error at this point. Therefore the else clause 
is selected.

This is one of the problems with using is(typeof) (or 
__traits(compiles)) with an "else" clause. You may not be checking what 
you think you are checking, and end up with the wrong result.

So essentially, Appender!(T[]) inside a T becomes (essentially) 
Appender!(void[]). And you can't append a T to a void[].

If I change the definition of ElementType to use R.init.front instead of 
R.init.front.init, it compiles. But I'm pretty sure this will break 
other ranges.

Somewhere, there's an answer.

-Steve


More information about the Digitalmars-d-learn mailing list