digitalmars.D.learn - Variadic Tuple of Structs with Mixed Types
- jmh530 (38/38) Jul 08 2016 I'm trying to create a tuple of variadic length containing
- ag0aep6g (41/74) Jul 08 2016 AliasSeq expands automatically. That means,
- jmh530 (2/29) Jul 09 2016 I'll give this a try. Thanks.
- jmh530 (49/143) Jul 15 2016 I was working with the lightweight wrapper and it seemed to work
- Michael Coulombe (21/32) Jul 15 2016 Your issue is this line:
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?
Jul 08 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); } ----
Jul 08 2016
On Saturday, 9 July 2016 at 05:40:10 UTC, ag0aep6g wrote:---- 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'll give this a try. Thanks.
Jul 09 2016
On Saturday, 9 July 2016 at 05:40:10 UTC, ag0aep6g wrote:On 07/09/2016 12:33 AM, jmh530 wrote: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 }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); } ----
Jul 15 2016
On Friday, 15 July 2016 at 17:00:09 UTC, jmh530 wrote: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.comYour issue is this line: alias boxAR(A) = Box!(A, R); This means that A must be a type, but you are trying to instantiate it with lambdas. If you switch to: alias boxAR(alias A) = Box!(A, R); But now you are back to the "local '__lambda1' as parameter to non-global template" error. Have you considered recursive solutions? template fillAliasSeq(R, f...) { import std.meta : AliasSeq; static if (f.length == 0) { alias fillAliasSeq = AliasSeq!(); } else { alias fillAliasSeq = AliasSeq!(Foo!(f[0], R), fillAliasSeq!(R, f[1..$])); } }
Jul 15 2016
On Friday, 15 July 2016 at 17:41:21 UTC, Michael Coulombe wrote:Your issue is this line: alias boxAR(A) = Box!(A, R); This means that A must be a type, but you are trying to instantiate it with lambdas. If you switch to: alias boxAR(alias A) = Box!(A, R); But now you are back to the "local '__lambda1' as parameter to non-global template" error.I had tried it a few different and ended up with errors like that.Have you considered recursive solutions?Will try that next. Thanks.
Jul 15 2016
On Friday, 15 July 2016 at 19:24:12 UTC, jmh530 wrote:I think this worked for me. A few tricks were that I had to have the fillAliasSeq template as global and also I couldn't disable the default constructor for what I was filling with it. Thanks for the help.Have you considered recursive solutions?Will try that next. Thanks.
Jul 18 2016