On Saturday, 9 July 2016 at 05:40:10 UTC, ag0aep6g wrote:
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);
}
----

I was working with the lightweight wrapper and it seemed to work for simple stuff, but then I started getting a bunch of errors when I tried to integrate it in to my project.

Below is the stripped down version of what I've been working with. I think the problem is that I can't get the fillAliasSeq template to work with aliases. If I change Foo to just take types and pass something like int or float, then it works fine.

Note, I originally had fillAliasSeq as a nested template within bar, but this was causing errors similar to what is brought up in this thread
http://forum.dlang.org/post/mailman.578.1343005779.31962.digitalmars-d-le...@puremagic.com




struct Foo(alias fun, R)
{

}

template fillAliasSeq(R, f...)
{
        import std.meta : staticMap;
        
        template Box(stuff...)
        {
                alias contents = stuff;
        }

        alias boxAR(A) = Box!(A, R);
        alias fillContents = staticMap!(boxAR, f);
        
        alias contents(alias box) = Foo!(box.contents);
        alias fillAliasSeq = staticMap!(contents, fillContents);
}

template bar(funs...)
{
        auto bar(int[] x)
        {
                import std.meta : staticMap;
                import std.typecons : Tuple;

                alias resultType = fillAliasSeq!(int[], funs);
                Tuple!(resultType) result;
                
                return result;
        }
}

void main()
{
        int[] x = [1, 2, 5, 9];
        alias f = (a, b) => a + b;
        alias g = (a, b) => a * b;

        //auto y = bar!(f, g)(x);             //this is what I want to do
        alias z = fillAliasSeq!(int[], f, g); //but I can't even do this
}



Reply via email to