I'm trying to experiment with templates and tried to implement templated arrays, something that can be declared like:
Array!(float, 3, 2, 1) myArray;
I've browsed through several implementations of this problem in C++ but I can't seem to convert it to D as I have little experience with the language (with D).
Anyways these are the stuff I tried, unfortunately none of them worked:
1. Compile-Time Functions - to generate code of the format
"DataType[D0][D1]...[Dn] Identifier"
import std.conv;
static string generateArray(D...)(string type, string identifier, D dimensions)
{
string result = type;
for(int i = 0; i < dimensions.length; i++)
{
result ~= "[" ~ to!(string)(dimensions[i]) ~ "]";
}
result ~= " " ~ identifier ~ ";";
return result;
}
int main(string[] args)
{
enum deb = generateArray("float", "data", 3, 2, 1);
pragma(msg, deb);
return 0;
}
Which I can wrap into a simple Array class
class Array(T, D...)
{
mixin(generateArray(T, "Data", D));
}
But this code fails with:
./template_recursion.d(10): Error: variable i cannot be read at compile time
./template_recursion.d(18): Error: template instance template_recursion.expandTuple!(int, int, int) error instantiating
./template_recursion.d(18): Error: CTFE failed because of previous errors in expandTuple
2. Recursive Templates - as stated earlier I have seen implementations of this in C++, but I can't seem to transform those statements into something the D compiler accepts.
template<class T, unsigned ... RestD> struct array;
template<class T, unsigned PrimaryD >
struct array<T, PrimaryD>
{
typedef T type[PrimaryD];
type data;
T& operator[](unsigned i) { return data[i]; }
};
template<class T, unsigned PrimaryD, unsigned ... RestD >
struct array<T, PrimaryD, RestD...>
{
typedef typename array<T, RestD...>::type OneDimensionDownArrayT;
typedef OneDimensionDownArrayT type[PrimaryD];
type data;
OneDimensionDownArrayT& operator[](unsigned i) { return data[i]; }
};