www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 12732] New: Add an Appender-like template that recursively

https://issues.dlang.org/show_bug.cgi?id=12732

          Issue ID: 12732
           Summary: Add an Appender-like template that recursively builds
                    a structure of Appender fields
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: Phobos
          Assignee: nobody puremagic.com
          Reporter: andrej.mitrovich gmail.com

This seems to be a common occurrence in my code:

-----
import std.array;

alias vec3 = int[3];

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

Model loadModel(string path)
{
    // note the code duplication here, needs to be tracked 
    // separately to the Model struct.
    Appender!(vec3[]) indices;
    Appender!(vec3[]) vertices;
    Appender!(vec3[]) normals;

    // ...
    // indices ~= 
    // vertices ~= 

    return Model(indices.data, vertices.data, normals.data);
}

void main() { }
-----

To avoid this code duplication it would be great to have a helper template that
can return an equivalent structure which contains Appender fields for all
internal arrays, and a convenience .data property function that returns the
original type. Here's one implementation:

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

alias vec3 = int[3];

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

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

     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;
    }
}

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

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

    // ...
    // result.indices ~=
    // result.vertices ~=

    return result.data;
}

void main() { }
-----

--
May 11 2014