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