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