Run-time Indexing of a Compile-Time Tuple

John Colvin via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue May 12 02:26:05 PDT 2015


On Monday, 11 May 2015 at 22:46:00 UTC, Per Nordlöw wrote:
> The pattern
>
>             final switch (_index)
>             {
>                 import std.range: empty, front;
>                 foreach (i, R; Rs)
>                 {
>                     case i:
>                         assert(!source[i].empty);
>                         return source[i].front;
>                 }
>             }
>
> occurring in roundRobin() and now also in my merge at
>
> https://github.com/nordlow/justd/blob/master/range_ex.d#L604
>
> is nor pretty nor concise.
>
> Is there a better way of indexing a compile time tuple with a 
> run-time index?
>
> It may have to work together with CommonType somehow as is 
> shown in my implementation of merge().

I wrote that code in roundRobin to replace a nightmare string 
mixin. I can't see any way of getting around it, as there is no 
meaningful CommonType for a tuple of arbitrary ranges. The body 
of each case statement needs to know the index at compile-time.

If the tuple genuinely did have a CommonType, then it would be 
easy to make a little free function (or member of 
std.typecons.tuple) to get this sort of result:

import std.typecons, std.traits;
CommonType!(T.Types) rtIdx(T)(T t, uint i)
if(is(T : Tuple!A, A...))
in
{
     assert(i < t.length);
}
body
{
     final switch(i)
     {
         foreach(ctI, m; t)
         {
             case ctI:
                 return t[ctI];
         }
     }
     assert(0);
}

unittest
{
     uint i = 2;
     Tuple!(int, long, byte) myTuple;
     myTuple[2] = 42;
     auto a = myTuple.rtIdx(i);
     static assert(is(typeof(a) == long));
     assert(a == 42);
}

You could probably extend this to take expression tuples as well 
or whatever the hell we call compiler tuples that contain runtime 
values these days.

Alternatively, you could make rtIndex return a struct that 
defines opIndex, so you could write
auto a = myTuple.rtIdx[i];

opSlice would be doable as well, to round it out.


More information about the Digitalmars-d-learn mailing list