www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Make a type tuple from an array

reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
Is there a way to turn an array (known at compile time) into a 
TypeTuple? I want to do a static foreach over it, like this:

     foreach(field; fields) {
         static if(is(mixin("T." ~ field.name))) { ... }
     }

Obviously that won't work, because we don't have a real static 
foreach yet.

I already worked around it with a string mixin, but I'd like to 
know whether there's a cleaner way...
Apr 10 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 10 April 2015 at 15:13:54 UTC, Marc Schütz wrote:
 Is there a way to turn an array (known at compile time) into a 
 TypeTuple? I want to do a static foreach over it, like this:

     foreach(field; fields) {
         static if(is(mixin("T." ~ field.name))) { ... }
     }

 Obviously that won't work, because we don't have a real static 
 foreach yet.

 I already worked around it with a string mixin, but I'd like to 
 know whether there's a cleaner way...
For input ranges in general: import std.range : isInputRange; template TypeTupleOf(TL...) if (TL.length == 1 && isInputRange!(typeof(TL[0]))) { import std.typetuple : TT = TypeTuple; enum r = TL[0]; static if (r.empty) alias TypeTupleOf = TT!(); else { enum f = r.front; alias TypeTupleOf = TT!( f, TypeTupleOf!( { auto tmp = r; tmp.popFront(); return tmp; }() ) ); } } unittest { import std.range : iota; foreach(i; TypeTupleOf!(iota(10))) { pragma(msg, i); } }
Apr 10 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 10 April 2015 at 15:36:42 UTC, John Colvin wrote:
 On Friday, 10 April 2015 at 15:13:54 UTC, Marc Schütz wrote:
 Is there a way to turn an array (known at compile time) into a 
 TypeTuple? I want to do a static foreach over it, like this:

    foreach(field; fields) {
        static if(is(mixin("T." ~ field.name))) { ... }
    }

 Obviously that won't work, because we don't have a real static 
 foreach yet.

 I already worked around it with a string mixin, but I'd like 
 to know whether there's a cleaner way...
For input ranges in general: import std.range : isInputRange; template TypeTupleOf(TL...) if (TL.length == 1 && isInputRange!(typeof(TL[0]))) { import std.typetuple : TT = TypeTuple; enum r = TL[0]; static if (r.empty) alias TypeTupleOf = TT!(); else { enum f = r.front; alias TypeTupleOf = TT!( f, TypeTupleOf!( { auto tmp = r; tmp.popFront(); return tmp; }() ) ); } } unittest { import std.range : iota; foreach(i; TypeTupleOf!(iota(10))) { pragma(msg, i); } }
Wow, thanks! I had to `import std.array : empty, front, popFront;`, but otherwise it works great. This should be in Phobos!
Apr 10 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 10 April 2015 at 17:53:31 UTC, Marc Schütz wrote:
 On Friday, 10 April 2015 at 15:36:42 UTC, John Colvin wrote:
 On Friday, 10 April 2015 at 15:13:54 UTC, Marc Schütz wrote:
 Is there a way to turn an array (known at compile time) into 
 a TypeTuple? I want to do a static foreach over it, like this:

   foreach(field; fields) {
       static if(is(mixin("T." ~ field.name))) { ... }
   }

 Obviously that won't work, because we don't have a real 
 static foreach yet.

 I already worked around it with a string mixin, but I'd like 
 to know whether there's a cleaner way...
For input ranges in general: import std.range : isInputRange; template TypeTupleOf(TL...) if (TL.length == 1 && isInputRange!(typeof(TL[0]))) { import std.typetuple : TT = TypeTuple; enum r = TL[0]; static if (r.empty) alias TypeTupleOf = TT!(); else { enum f = r.front; alias TypeTupleOf = TT!( f, TypeTupleOf!( { auto tmp = r; tmp.popFront(); return tmp; }() ) ); } } unittest { import std.range : iota; foreach(i; TypeTupleOf!(iota(10))) { pragma(msg, i); } }
Wow, thanks! I had to `import std.array : empty, front, popFront;`, but otherwise it works great.
Haha, yeah... I forgot where they were, they aren't documented in std.array (grrrr), so I just left it for someone else to find :p
 This should be in Phobos!
Yup. I've mentioned it here: https://github.com/D-Programming-Language/phobos/pull/3128 but it's a bit of a complicated situation as a bunch of names are likely to change.
Apr 10 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 10 April 2015 at 18:25:14 UTC, John Colvin wrote:
 This should be in Phobos!
Yup. I've mentioned it here: https://github.com/D-Programming-Language/phobos/pull/3128 but it's a bit of a complicated situation as a bunch of names are likely to change.
I had seen the PR, but didn't mentally connect it with std.typetuple. Now I see it's intended as a replacement for it. Good that it won't get lost.
Apr 10 2015
prev sibling next sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Friday, 10 April 2015 at 15:36:42 UTC, John Colvin wrote:
     if (TL.length == 1 && isInputRange!(typeof(TL[0])))
Why not use isStaticArray instead of isInputRange here?
Apr 10 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 10 April 2015 at 22:55:23 UTC, Nordlöw wrote:
 On Friday, 10 April 2015 at 15:36:42 UTC, John Colvin wrote:
    if (TL.length == 1 && isInputRange!(typeof(TL[0])))
Why not use isStaticArray instead of isInputRange here?
Because that would be completely different. Static arrays aren't even input ranges...
Apr 11 2015
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Saturday, 11 April 2015 at 07:18:26 UTC, John Colvin wrote:
 Why not use isStaticArray instead of isInputRange here?
Because that would be completely different. Static arrays aren't even input ranges...
Ahh, my mistake. Could somebody explain when this feature is needed?
Apr 11 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Saturday, 11 April 2015 at 09:05:19 UTC, Nordlöw wrote:
 On Saturday, 11 April 2015 at 07:18:26 UTC, John Colvin wrote:
 Why not use isStaticArray instead of isInputRange here?
Because that would be completely different. Static arrays aren't even input ranges...
Ahh, my mistake. Could somebody explain when this feature is needed?
Code generation. Doing string mixin for each element of the array (won't work with plain foreach over array as it does runtime iteration)
Apr 11 2015
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 11 April 2015 at 09:23:11 UTC, Dicebot wrote:
 On Saturday, 11 April 2015 at 09:05:19 UTC, Nordlöw wrote:
 On Saturday, 11 April 2015 at 07:18:26 UTC, John Colvin wrote:
 Why not use isStaticArray instead of isInputRange here?
Because that would be completely different. Static arrays aren't even input ranges...
Ahh, my mistake. Could somebody explain when this feature is needed?
Code generation. Doing string mixin for each element of the array (won't work with plain foreach over array as it does runtime iteration)
Generating case statements is a nice example use that doesn't (necessarily) involve string mixins.
Apr 11 2015
prev sibling parent Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On 04/10/15 17:36, John Colvin via Digitalmars-d-learn wrote:
 On Friday, 10 April 2015 at 15:13:54 UTC, Marc Schütz wrote:
 Is there a way to turn an array (known at compile time) into a TypeTuple? 
 For input ranges in general:
 
 import std.range : isInputRange;
 
 template TypeTupleOf(TL...)
     if (TL.length == 1 && isInputRange!(typeof(TL[0])))
 {
     import std.typetuple : TT = TypeTuple;
     enum r = TL[0];
     static if (r.empty)
         alias TypeTupleOf = TT!();
     else
     {
         enum f = r.front;
         alias TypeTupleOf = TT!(
             f,
             TypeTupleOf!(
                 { auto tmp = r; tmp.popFront(); return tmp; }()
                 )
             );
     }
 }
Neat, but very unreadable... import std.array, std.range : isInputRange, dropOne; template TypeTupleOf(alias R) if (isInputRange!(typeof(R))) { import std.typetuple : TT = TypeTuple; static if (R.empty) alias TypeTupleOf = TT!(); else alias TypeTupleOf = TT!(R.front(), TypeTupleOf!(R.dropOne())); } artur
Apr 11 2015