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));
}

Reply via email to