On 07/09/2016 12:33 AM, jmh530 wrote:
I'm trying to create a tuple of variadic length containing structs with
mixed types. So for instance, given

struct Foo(T, U)
{
     T x;
     U y;
}

I want to create something like
Tuple!(Foo!(type1, type2), Foo!(type1, type3), ..., Foo!(type1, typeN)) x;

The bar function (below) is what I've tried to use to create it.

template bar(T, U...)
     if (U.length > 1)
{

     import std.meta : staticMap;

     template baz(A)
     {
         import std.meta : AliasSeq;

         alias baz = AliasSeq!(T, A);
     }

     alias V = staticMap!(baz, U);
     alias bar = staticMap!(Foo, V);
}

void main()
{
     import std.typecons : Tuple;

     Tuple!(bar!(int, float, int)) x;
}

My strategy was getting something like
AliasSeq!(AliasSeq!(type1, type2), AliasSeq!(type1, type3), ... )
and then I can staticMap over that with Foo in order to create the
correct type.

However, I can't seem to get it working.

Any ideas?

AliasSeq expands automatically. That means,

    AliasSeq!(AliasSeq!(type1, type2), AliasSeq!(type1, type3))

is the same as

    AliasSeq!(type1, type2, type1, type3)

You can see this in action with `pragma(msg, V);` which prints "(int, float, int, int)".

Obviously, the next staticMap fails then, because it gets handed a list of individual types, but it should operate on pairs of types.

You need to wrap your pairs in something stronger than AliasSeq. You can use a std.typecons.Tuple or a little custom template. Then you need to unwrap it before applying Foo, because Foo works on a pair of types not a Tuple or custom wrapper.

Putting it together:

----
template bar(T, U...)
if (U.length > 1)
{
    import std.meta : staticMap;
    import std.typecons : Tuple;

    alias baz(A) = Tuple!(T, A);
    alias V = staticMap!(baz, U);
    alias TupleToFoo(T : Tuple!(Types), Types ...) = Foo!Types;
    // Alternative TupleToFoo with less complex syntax:
    // alias TupleToFoo(T) = Foo!(T.Types);
    alias bar = staticMap!(TupleToFoo, V);
}
----

Or with a more lightweight, custom wrapper:

----
template bar(T, U...)
if (U.length > 1)
{
    import std.meta : staticMap;

    template Box(stuff ...) { alias contents = stuff; }

    alias baz(A) = Box!(T, A);
    alias V = staticMap!(baz, U);
    alias BoxToFoo(alias box) = Foo!(box.contents);
    alias bar = staticMap!(BoxToFoo, V);
}
----

Reply via email to