Thread overview
[Issue 12732] Add an Appender-like template that recursively builds a structure of Appender fields
May 11, 2014
Andrej Mitrovic
May 11, 2014
Andrej Mitrovic
May 11, 2014
Andrej Mitrovic
May 11, 2014
Andrej Mitrovic
Jul 06, 2022
Andrej Mitrovic
May 11, 2014
https://issues.dlang.org/show_bug.cgi?id=12732

--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> ---
Oops, I failed to properly test that implementation. Lemme fix that up real soon.

--
May 11, 2014
https://issues.dlang.org/show_bug.cgi?id=12732

--- Comment #2 from Andrej Mitrovic <andrej.mitrovich@gmail.com> ---
Here's a working version, unfortunately I again had to resort to string mixins:

-----
import std.array;
import std.string;
import std.typetuple;

alias vec3 = int[3];

template ApplyAppender(alias S)
{
    static if (is(typeof(S) : E[], E))
        enum ApplyAppender = format("Appender!(%s) %s;", typeof(S).stringof,
__traits(identifier, S));
    else
        enum ApplyAppender = format("%s %s;", typeof(S).stringof,
__traits(identifier, S));
}

string generate(T)()
{
    string[] res;

    foreach (str; staticMap!(ApplyAppender, T.tupleof))
        res ~= str;

    return res.join("\n");
}

struct AppenderWrapper(T)
{
    mixin(generate!T);

    @property T data()
    {
        T res;

        foreach (idx, field; this.tupleof)
        {
            static if (is(typeof(res.tupleof[idx]) : E[], E))
                res.tupleof[idx] = field.data;
            else
                res.tupleof[idx] = field;
        }

        return res;
    }
}

///
struct Model
{
    vec3[] indices;
    vec3[] vertices;
    vec3[] normals;
    int other;
}

Model loadModel(string path)
{
    AppenderWrapper!(typeof(return)) result;

    vec3 vec;
    result.indices ~= vec;
    result.vertices ~= vec;
    result.normals ~= vec;
    result.other = 5;

    return result.data;
}

void main() { }
-----

--
May 11, 2014
https://issues.dlang.org/show_bug.cgi?id=12732

--- Comment #3 from Andrej Mitrovic <andrej.mitrovich@gmail.com> ---
And because of string mixins the mixin() won't work if the type is from another module which isn't imported. Well maybe we can implement this without string mixins somehow.

--
May 11, 2014
https://issues.dlang.org/show_bug.cgi?id=12732

--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> ---
There we go:

-----
import std.array;
import std.string;
import std.typetuple;

alias ApplyAppender(T : E[], E) = Appender!T;
alias ApplyAppender(T) = T;

enum Identifier(alias S) = __traits(identifier, S);

string generateAliases(T)()
{
    string[] res;

    foreach (idx, str; staticMap!(Identifier, T.tupleof))
        res ~= format("alias %s = fields[%s];", str, idx);

    return res.join("\n");
}

struct AppenderWrapper(T)
{
    alias Fields = staticMap!(ApplyAppender, typeof(T.tupleof));
    Fields fields;

    mixin(generateAliases!T);

    @property T data()
    {
        T res;

        foreach (idx, field; fields)
        {
            static if (is(typeof(res.tupleof[idx]) : E[], E))
                res.tupleof[idx] = field.data;
            else
                res.tupleof[idx] = field;
        }

        return res;
    }
}

alias vec3 = int[3];

struct Model
{
    vec3[] indices;
    vec3[] vertices;
    vec3[] normals;
    int other;
}

Model loadModel(string path)
{
    AppenderWrapper!(typeof(return)) result;

    vec3 vec;
    result.indices ~= vec;
    result.vertices ~= vec;
    result.normals ~= vec;
    result.other = 1;

    return result.data;
}

void main() { }
-----

--
July 06, 2022
https://issues.dlang.org/show_bug.cgi?id=12732

Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |WONTFIX

--- Comment #5 from Andrej Mitrovic <andrej.mitrovich@gmail.com> ---
This doesn't need to be part of Phobos, it's a very specific use-case that can easily be implemented in a user library (or even just a few lines of code these days).

--