Variadic Tuple of Structs with Mixed Types
jmh530 via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Jul 15 10:00:09 PDT 2016
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-learn@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
}
More information about the Digitalmars-d-learn
mailing list