Variadic Tuple of Structs with Mixed Types

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Jul 8 22:40:10 PDT 2016


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


More information about the Digitalmars-d-learn mailing list