digitalmars.D.learn - Dimensions in compile time
- Vindex (5/5) Feb 08 2021 size_t ndim(A)(A arr) {
- Basile B. (28/33) Feb 08 2021 yeah.
- Basile B. (4/33) Feb 08 2021 well I didn't realize but static array are not handled. I think
- Vindex (19/19) Feb 08 2021 Thanks everyone!
- Basile B. (4/23) Feb 08 2021 Nice. You should look at Rumbu solution too. It possibly has a
- Rumbu (15/49) Feb 08 2021 dimensionCount!string should be 2.
- Basile B. (3/19) Feb 08 2021 yeah you're right, strings were a special case (I remember now)
- Basile B. (4/28) Feb 08 2021 well to OP just dont use my dimensionCount template ^^. it should
- Petar Kirov [ZombineDev] (55/108) Feb 08 2021 Here's the version I actually wanted to write:
size_t ndim(A)(A arr) { return std.algorithm.count(typeid(A).to!string, '['); } Is there a way to find out the number of dimensions in an array at compile time?
Feb 08 2021
On Monday, 8 February 2021 at 11:42:45 UTC, Vindex wrote:size_t ndim(A)(A arr) { return std.algorithm.count(typeid(A).to!string, '['); } Is there a way to find out the number of dimensions in an array at compile time?yeah. --- template dimensionCount(T) { static if (isArray!T) { static if (isMultiDimensionalArray!T) { alias DT = typeof(T.init[0]); enum dimensionCount = dimensionCount!DT + 1; } else enum dimensionCount = 1; } else enum dimensionCount = 0; } /// unittest { static assert(dimensionCount!char == 0); static assert(dimensionCount!(string[]) == 1); static assert(dimensionCount!(int[]) == 1); static assert(dimensionCount!(int[][]) == 2); static assert(dimensionCount!(int[][][]) == 3); } --- that can be rewritten using some phobos traits too I think, but this piece of code is very old now, more like learner template.
Feb 08 2021
On Monday, 8 February 2021 at 12:19:26 UTC, Basile B. wrote:On Monday, 8 February 2021 at 11:42:45 UTC, Vindex wrote:well I didn't realize but static array are not handled. I think this is because in first place this was made for a specific usage that was a serializer.[...]yeah. --- template dimensionCount(T) { static if (isArray!T) { static if (isMultiDimensionalArray!T) { alias DT = typeof(T.init[0]); enum dimensionCount = dimensionCount!DT + 1; } else enum dimensionCount = 1; } else enum dimensionCount = 0; } /// unittest { static assert(dimensionCount!char == 0); static assert(dimensionCount!(string[]) == 1); static assert(dimensionCount!(int[]) == 1); static assert(dimensionCount!(int[][]) == 2); static assert(dimensionCount!(int[][][]) == 3); } --- that can be rewritten using some phobos traits too I think, but this piece of code is very old now, more like learner template.
Feb 08 2021
Thanks everyone! The solution that works for me now looks like this: template ndim(T) { static if (std.traits.isArray!T) { static if (is(typeof(T.init[0]))) { alias SubArrayType = typeof(T.init[0]); enum ndim = ndim!SubArrayType + 1; } else enum ndim = 1; } else enum ndim = 0; } unittest { assert(ndim!(int[]) == 1); assert(ndim!(int[][]) == 2); assert(ndim!(int[4][3]) == 2); assert(ndim!(int[][2][]) == 3); assert(ndim!(string) == 1); }
Feb 08 2021
On Monday, 8 February 2021 at 13:27:14 UTC, Vindex wrote:Thanks everyone! The solution that works for me now looks like this: template ndim(T) { static if (std.traits.isArray!T) { static if (is(typeof(T.init[0]))) { alias SubArrayType = typeof(T.init[0]); enum ndim = ndim!SubArrayType + 1; } else enum ndim = 1; } else enum ndim = 0; } unittest { assert(ndim!(int[]) == 1); assert(ndim!(int[][]) == 2); assert(ndim!(int[4][3]) == 2); assert(ndim!(int[][2][]) == 3); assert(ndim!(string) == 1); }Nice. You should look at Rumbu solution too. It possibly has a better behavior toward the recursive expansion. Also interesting to learn the more advanced use of "is".
Feb 08 2021
On Monday, 8 February 2021 at 12:19:26 UTC, Basile B. wrote:On Monday, 8 February 2021 at 11:42:45 UTC, Vindex wrote:dimensionCount!string should be 2. My take without std.traits: template rank(T: U[], U) { enum rank = 1 + rank!U; } template rank(T: U[n], size_t n) { enum rank = 1 + rank!U; } template rank(T) { enum rank = 0; }size_t ndim(A)(A arr) { return std.algorithm.count(typeid(A).to!string, '['); } Is there a way to find out the number of dimensions in an array at compile time?yeah. --- template dimensionCount(T) { static if (isArray!T) { static if (isMultiDimensionalArray!T) { alias DT = typeof(T.init[0]); enum dimensionCount = dimensionCount!DT + 1; } else enum dimensionCount = 1; } else enum dimensionCount = 0; } /// unittest { static assert(dimensionCount!char == 0); static assert(dimensionCount!(string[]) == 1); static assert(dimensionCount!(int[]) == 1); static assert(dimensionCount!(int[][]) == 2); static assert(dimensionCount!(int[][][]) == 3); } --- that can be rewritten using some phobos traits too I think, but this piece of code is very old now, more like learner template.
Feb 08 2021
On Monday, 8 February 2021 at 13:09:53 UTC, Rumbu wrote:On Monday, 8 February 2021 at 12:19:26 UTC, Basile B. wrote:yeah you're right, strings were a special case (I remember now) so that stuff could be stored as literals.[...]dimensionCount!string should be 2. My take without std.traits: template rank(T: U[], U) { enum rank = 1 + rank!U; } template rank(T: U[n], size_t n) { enum rank = 1 + rank!U; } template rank(T) { enum rank = 0; }
Feb 08 2021
On Monday, 8 February 2021 at 13:13:33 UTC, Basile B. wrote:On Monday, 8 February 2021 at 13:09:53 UTC, Rumbu wrote:well to OP just dont use my dimensionCount template ^^. it should have been declared with the "package" protection in first place; not public.On Monday, 8 February 2021 at 12:19:26 UTC, Basile B. wrote:yeah you're right, strings were a special case (I remember now) so that stuff could be stored as literals.[...]dimensionCount!string should be 2. My take without std.traits: template rank(T: U[], U) { enum rank = 1 + rank!U; } template rank(T: U[n], size_t n) { enum rank = 1 + rank!U; } template rank(T) { enum rank = 0; }
Feb 08 2021
On Monday, 8 February 2021 at 13:09:53 UTC, Rumbu wrote:On Monday, 8 February 2021 at 12:19:26 UTC, Basile B. wrote:Here's the version I actually wanted to write: --- enum rank(T) = is(T : U[], U) ? 1 + rank!U : 0; --- But it's not possible, because of 2 language limitations: 1. Ternary operator doesn't allow the different branches to be specialized like `static if` even if the condition is a compile-time constant. 2. `is()` expressions can only introduce an identifier if inside a `static if`. Otherwise, I'd consider this the "idiomatic" / "typical" D solution, since unlike C++, D code rarely (*) overloads and specializes templates. (*) Modern Phobos(-like) code. --- template rank(T) { static if (is(T : U[], U)) enum rank = 1 + rank!U; else enum rank = 0; } unittest { static assert( rank!(char) == 0); static assert( rank!(char[]) == 1); static assert( rank!(string) == 1); static assert( rank!(string[]) == 2); static assert( rank!(string[][]) == 3); static assert( rank!(string[][][]) == 4); } --- Otherwise, the shortest and cleanest solution IMO is this one: --- enum rank(T : U[], U) = is(T : U[], U) ? 1 + rank!U : 0; enum rank(T) = 0; unittest { static assert( rank!(char) == 0); static assert( rank!(char[]) == 1); static assert( rank!(string) == 1); static assert( rank!(string[]) == 2); static assert( rank!(string[][]) == 3); static assert( rank!(string[][][]) == 4); static assert( rank!(char) == 0); static assert( rank!(char[1]) == 1); static assert( rank!(char[1][2]) == 2); static assert( rank!(char[1][2][3]) == 3); static assert( rank!(char[1][2][3][4]) == 4); } --- - Use eponymous template syntax shorthand - Static arrays are implicitly convertible to dynamic arrays, so we can merge the two implementations.On Monday, 8 February 2021 at 11:42:45 UTC, Vindex wrote:dimensionCount!string should be 2. My take without std.traits: template rank(T: U[], U) { enum rank = 1 + rank!U; } template rank(T: U[n], size_t n) { enum rank = 1 + rank!U; } template rank(T) { enum rank = 0; }size_t ndim(A)(A arr) { return std.algorithm.count(typeid(A).to!string, '['); } Is there a way to find out the number of dimensions in an array at compile time?yeah. --- template dimensionCount(T) { static if (isArray!T) { static if (isMultiDimensionalArray!T) { alias DT = typeof(T.init[0]); enum dimensionCount = dimensionCount!DT + 1; } else enum dimensionCount = 1; } else enum dimensionCount = 0; } /// unittest { static assert(dimensionCount!char == 0); static assert(dimensionCount!(string[]) == 1); static assert(dimensionCount!(int[]) == 1); static assert(dimensionCount!(int[][]) == 2); static assert(dimensionCount!(int[][][]) == 3); } --- that can be rewritten using some phobos traits too I think, but this piece of code is very old now, more like learner template.
Feb 08 2021