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