On Wednesday, 17 June 2015 at 19:53:07 UTC, jmh530 wrote:
I want to write a function template that works for any array of
a particular type, but not the base type, so real[], real[][],
etc, but not real. I was using ForeachType to do some testing,
but it doesn't really get the base type. It just takes one of
the [] off and returns the remaining type (see code below).
ElementType from std.range seems to operate in a similar way.
There are also ways to do this for associative arrays, but they
don't apply here either.
How do I go about just getting the actual base type of an array?
import std.stdio;
import std.traits;
void main() {
real[2] x;
x[0] = 0;
x[1] = 1;
writeln(is(ForeachType!(typeof(x)) == real)); //prints true
real[2][2] xx;
xx[0][0] = 0;
xx[1][0] = 1;
xx[0][1] = 2;
xx[1][1] = 3;
writeln(is(ForeachType!(typeof(xx)) == real)); //prints false
writeln(typeid(ForeachType!(typeof(xx))); //prints
real[2]
}
Here is another solution which is more general in that it can be
used with any input range.
import std.range: isInputRange;
import std.array;
template FlattenedType(R, int depth = int.max)
if (isInputRange!R && depth >= 0)
{
static if (depth == 0)
{
alias FlattenedType = R;
}
else
{
alias FrontType = typeof(R.init.front);
static if (isInputRange!FrontType)
{
alias FlattenedType = FlattenedType!(FrontType, depth -
1);
}
else
{
alias FlattenedType = R;
}
}
}
alias ArrayBaseType(T: U[], U) =
typeof(FlattenedType!T.init.front);
void main()
{
assert(is(FlattenedType!(int[][][]) == int[]));
assert(is(ArrayBaseType!(int[][][]) == int));
}