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