digitalmars.D.learn - Base type for arrays
- jmh530 (26/26) Jun 17 2015 I want to write a function template that works for any array of a
- Alex Parrill (8/35) Jun 17 2015 Try:
- jmh530 (8/15) Jun 17 2015 I don't think this works for multi-dimensional arrays. I tried
- Alex Parrill (10/28) Jun 17 2015 Yea, it doesn't, it only goes one-level deep. I misunderstood.
- Namespace (28/28) Jun 17 2015 ----
- Meta (32/59) Jun 17 2015 Here is another solution which is more general in that it can be
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] }
Jun 17 2015
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] }Try: void foo(T)(T[] arg) { // In here, T should be the element type, and T[] the array type. } Not a general solution, but you mentioned that you wanted this for a function parameter.
Jun 17 2015
On Wednesday, 17 June 2015 at 20:06:54 UTC, Alex Parrill wrote:Try: void foo(T)(T[] arg) { // In here, T should be the element type, and T[] the array type. } Not a general solution, but you mentioned that you wanted this for a function parameter.I don't think this works for multi-dimensional arrays. I tried void foo(T)(T[] arg) if (isArray!(T[]) && is(T == real)) { writeln("foo has run for ", arg); } and it only worked on the one-dimensional one.
Jun 17 2015
On Wednesday, 17 June 2015 at 20:20:29 UTC, jmh530 wrote:On Wednesday, 17 June 2015 at 20:06:54 UTC, Alex Parrill wrote:Yea, it doesn't, it only goes one-level deep. I misunderstood. Here's a recursive template: template ArrayBaseType(T) { static if(is(T : U[], U)) alias ArrayBaseType = ArrayBaseType!U; else alias ArrayBaseType = T; } pragma(msg, ArrayBaseType!(int[][][])); // prints 'int'Try: void foo(T)(T[] arg) { // In here, T should be the element type, and T[] the array type. } Not a general solution, but you mentioned that you wanted this for a function parameter.I don't think this works for multi-dimensional arrays. I tried void foo(T)(T[] arg) if (isArray!(T[]) && is(T == real)) { writeln("foo has run for ", arg); } and it only worked on the one-dimensional one.
Jun 17 2015
---- import std.stdio; template BaseTypeOf(T) { static if (is(T : U[], U)) alias BaseTypeOf = BaseTypeOf!(U); else alias BaseTypeOf = T; } void foo(T : U[], U)(T arr) if (is(BaseTypeOf!(U) == real)) { } void main() { //real _x; real[2] x; real[2][2] xx; real[2][2][2] xxx; //float[2] yy; //foo(_x); foo(x); foo(xx); foo(xxx); //foo(yy); } ---- should work
Jun 17 2015
On Wednesday, 17 June 2015 at 20:33:11 UTC, Namespace wrote:---- import std.stdio; template BaseTypeOf(T) { static if (is(T : U[], U)) alias BaseTypeOf = BaseTypeOf!(U); else alias BaseTypeOf = T; } void foo(T : U[], U)(T arr) if (is(BaseTypeOf!(U) == real)) { } void main() { //real _x; real[2] x; real[2][2] xx; real[2][2][2] xxx; //float[2] yy; //foo(_x); foo(x); foo(xx); foo(xxx); //foo(yy); } ---- should workThanks. I'm going to make a lot of use of this. I would say it deserves to be in std.traits.
Jun 17 2015
On Wednesday, 17 June 2015 at 20:58:10 UTC, jmh530 wrote:On Wednesday, 17 June 2015 at 20:33:11 UTC, Namespace wrote:Maybe you can also make use of some of those here (just in case): https://github.com/Dgame/m3/blob/master/source/m3/m3.d---- import std.stdio; template BaseTypeOf(T) { static if (is(T : U[], U)) alias BaseTypeOf = BaseTypeOf!(U); else alias BaseTypeOf = T; } void foo(T : U[], U)(T arr) if (is(BaseTypeOf!(U) == real)) { } void main() { //real _x; real[2] x; real[2][2] xx; real[2][2][2] xxx; //float[2] yy; //foo(_x); foo(x); foo(xx); foo(xxx); //foo(yy); } ---- should workThanks. I'm going to make a lot of use of this. I would say it deserves to be in std.traits.
Jun 17 2015
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)); }
Jun 17 2015