Reputation: 16168
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
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:
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.
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