Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
June 17, 2015 Base type for arrays | ||||
---|---|---|---|---|
| ||||
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] } |
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | 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.
|
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex Parrill | 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.
|
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | 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:
>
>>
>> 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.
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'
|
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | ---- 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 |
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 work
Thanks. I'm going to make a lot of use of this. I would say it deserves to be in std.traits.
|
June 17, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | On Wednesday, 17 June 2015 at 20:58:10 UTC, jmh530 wrote: > 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 work > > Thanks. I'm going to make a lot of use of this. I would say it deserves to be in std.traits. 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 |
June 18, 2015 Re: Base type for arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | 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)); } |
Copyright © 1999-2021 by the D Language Foundation