Maik Klein
Maik Klein

Reputation: 16168

How to create a tuple of ranges?

template tupIndexToRange(alias Tup, Indicies...){
  import std.meta;
  import std.typecons;
  static if(Indicies.length == 0){
    enum tupIndexToRange = tuple();
  }
  else{
    enum tupIndexToRange = tuple(Tup[ Indicies[0] ][], tupIndexToRange!(Tup,Indicies[1..$]));
  }
}

void main(){
  alias Integrals = AliasSeq!(Array!int, Array!float, Array!double);
  Tuple!Integrals integrals;
  integrals[0].insertBack(1);
  integrals[1].insertBack(2);
  integrals[2].insertBack(3);
  auto t = tupIndexToRange!(integrals, 0, 1, 2);
  auto r = zip(t.expand);
}

err:

source/app.d(119,34): Error: variable integrals cannot be read at compile time
source/app.d(119,33):        called from here: tuple(integrals.__expand_field_2.opSlice(), Tuple())
source/app.d(119,56): Error: template instance app.main.tupIndexToRange!(integrals, 2) error instantiating
source/app.d(119,56):        instantiated from here: tupIndexToRange!(integrals, 1, 2)
source/app.d(219,12):        instantiated from here: tupIndexToRange!(integrals, 0, 1, 2)

I assume this error appears because I am trying to access the range at compile time? How would I tell D that I only need to access the range at run time?

This is what tupIndexToRange should do:

auto t = tuple(integrals[0][], integrals[1][], integrals[2][]);

Upvotes: 3

Views: 72

Answers (1)

rcorre
rcorre

Reputation: 7258

How would I tell D that I only need to access the range at run time?

By passing it as a runtime parameter:

template tupIndexToRange(Indicies...) {
    auto tupIndexToRange(T)(T tup) {
      static if(Indicies.length == 0){
        return tuple();
      }
      else{
        return tuple(tup[ Indicies[0] ][], .tupIndexToRange!(Indicies[1..$])(tup).expand);
      }
    }
}

Two things to note:

  1. The function nested in the template allows us to just specify the indices and not the type. If it were just auto tupIndexToRange(T, Indices)(T tup), we woul have to provide the type explicitly.

  2. We recurse by calling .tupIndexToRange rather than tupIndexToRange, as we want to recurse via the template in the outer scope, not the nested function.

Upvotes: 4

Related Questions