digitalmars.D.learn - How to get the element type of an array?
- Jon Degenhardt (6/6) Aug 24 2020 What's the best way to get the element type of an array at
- Harry Gillanders (9/15) Aug 24 2020 One way (maybe not the best way) is to use the type of the
- H. S. Teoh (22/28) Aug 24 2020 [...]
- Jon Degenhardt (6/7) Aug 24 2020 Harry Gillanders, H.S. Teoh,
- Basile B. (3/9) Aug 24 2020 I'm curious to know what are the array types that were not
- Jon Degenhardt (44/59) Aug 25 2020 Interesting. I need to test static arrays. In fact 'ElementType'
- Steven Schveighoffer (15/37) Aug 25 2020 Also note that due to autodecoding, ElementType says `dchar` for
- Jon Degenhardt (20/28) Aug 25 2020 This is a good characteristic. But the reason it surprised me was
- FreeSlave (4/10) Aug 25 2020 Why not just use typeof(a[0])
- H. S. Teoh (5/19) Aug 25 2020 +1, why didn't I think of this before. :-D
- Jon Degenhardt (3/16) Aug 25 2020 Wow, yet another way that should have been obvious! Thanks!
What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --Jon
Aug 24 2020
On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonOne way (maybe not the best way) is to use the type of the array's ptr property when dereferenced, e.g. import std.traits : isArray; template ArrayElementOf (Array) if (isArray!Array) { alias ArrayElementOf = typeof(*Array.init.ptr); }
Aug 24 2020
On Tue, Aug 25, 2020 at 03:41:06AM +0000, Jon Degenhardt via Digitalmars-d-learn wrote:What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing.[...] alias T = ... /* the type to inspect */ static if (is(T : E[], E)) { ... /* in this block, E is the element type */ } Or if you need to use it in another expression: template ArrayElemType(T) { static if (is(T : E[], E)) { alias ArrayElemType = E; } else alias ArrayElemType = void; // or static assert(0) if it should be an error } int[] myArr; pragma(msg, ArrayElemType!(typeof(myArr))); // int string myStr; pragma(msg, ArrayElemType!(typeof(myStr))); // immutable(char) T -- The best way to destroy a cause is to defend it poorly.
Aug 24 2020
On Tuesday, 25 August 2020 at 04:36:56 UTC, H. S. Teoh wrote:[...]Harry Gillanders, H.S. Teoh, Thank you both for the quick replies. Both methods address my needs. Very much appreciated, I was having trouble figuring this one out. --Jon
Aug 24 2020
On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonI'm curious to know what are the array types that were not accepted by ElementType ( or ElementEncodingType ) ?
Aug 24 2020
On Tuesday, 25 August 2020 at 05:02:46 UTC, Basile B. wrote:On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:Interesting. I need to test static arrays. In fact 'ElementType' does work with static arrays. Which is likely what you expected. I assumed ElementType would not work, because static arrays don't satisfy 'isInputRange', and the documentation for ElementType says:What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonI'm curious to know what are the array types that were not accepted by ElementType ( or ElementEncodingType ) ?The element type is determined as the type yielded by r.front for an object r of type R. [...] If R doesn't have front, ElementType!R is void.But, if std.range is imported, a static array does indeed get a 'front' member. It doesn't satisfy isInputRange, but it does have a 'front' element. The situation is still confusing though. If only 'std.range.ElementType' is imported, a static array does not have a 'front' member, but ElementType still gets the correct type. (This is where the documentation says it'll return void.) --- Import std.range --- safe unittest { import std.range; ubyte[10] staticArray; ubyte[] dynamicArray = new ubyte[](10); static assert(is(ElementType!(typeof(staticArray)) == ubyte)); static assert(is(ElementType!(typeof(dynamicArray)) == ubyte)); // front is available static assert(__traits(compiles, staticArray.front)); static assert(__traits(compiles, dynamicArray.front)); static assert(is(typeof(staticArray.front) == ubyte)); static assert(is(typeof(dynamicArray.front) == ubyte)); } --- Import std.range.ElementType --- safe unittest { import std.range : ElementType; ubyte[10] staticArray; ubyte[] dynamicArray = new ubyte[](10); static assert(is(ElementType!(typeof(staticArray)) == ubyte)); static assert(is(ElementType!(typeof(dynamicArray)) == ubyte)); // front is not available static assert(!__traits(compiles, staticArray.front)); static assert(!__traits(compiles, dynamicArray.front)); static assert(!is(typeof(staticArray.front) == ubyte)); static assert(!is(typeof(dynamicArray.front) == ubyte)); } This suggests the documentation for ElementType not quite correct.
Aug 25 2020
On 8/25/20 4:38 AM, Jon Degenhardt wrote:On Tuesday, 25 August 2020 at 05:02:46 UTC, Basile B. wrote:Also note that due to autodecoding, ElementType says `dchar` for strings. ElementEncodingType should be the choice if you are looking for the array element type. But you could also use the techniques specified here (and might be less confusing).On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:Interesting. I need to test static arrays. In fact 'ElementType' does work with static arrays. Which is likely what you expected.What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonI'm curious to know what are the array types that were not accepted by ElementType ( or ElementEncodingType ) ?But, if std.range is imported, a static array does indeed get a 'front' member. It doesn't satisfy isInputRange, but it does have a 'front' element.Because you can't pop the front of a static array. front works because a static array automatically casts to a normal array (there is no specialized overload for static arrays).The situation is still confusing though. If only 'std.range.ElementType' is imported, a static array does not have a 'front' member, but ElementType still gets the correct type. (This is where the documentation says it'll return void.)You are maybe thinking of how C works? D imports are different, the code is defined the same no matter how it is imported. *your* module cannot see std.range.primitives.front, but the range module itself can see that UFCS function. This is also why ElementType will fail on types that have UFCS front defined, but not imported directly from std.range.primitives. -Steve
Aug 25 2020
On Tuesday, 25 August 2020 at 12:50:35 UTC, Steven Schveighoffer wrote:This is a good characteristic. But the reason it surprised me was that I expected to be able to manually expand the ElementType (or ElementEncodingType) template see the results of the expressions it uses. template ElementType(R) { static if (is(typeof(R.init.front.init) T)) alias ElementType = T; else alias ElementType = void; } So, yes, I was expecting this to behave like an inline code expansion. Yesterday I was doing that for 'hasSlicing', which has a more complicated set of tests. I wanted to see exactly which expression in 'hasSlicing' was causing it to return false for a struct I wrote. (Turned out to be a test for 'length'.) I'll have to be more careful about this.The situation is still confusing though. If only 'std.range.ElementType' is imported, a static array does not have a 'front' member, but ElementType still gets the correct type. (This is where the documentation says it'll return void.)You are maybe thinking of how C works? D imports are different, the code is defined the same no matter how it is imported. *your* module cannot see std.range.primitives.front, but the range module itself can see that UFCS function.
Aug 25 2020
On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonWhy not just use typeof(a[0]) It does not matter if array is empty or not. Typeof does not actually evaluate its expression, just the type.
Aug 25 2020
On Tue, Aug 25, 2020 at 03:02:14PM +0000, FreeSlave via Digitalmars-d-learn wrote:On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:+1, why didn't I think of this before. :-D T -- Political correctness: socially-sanctioned hypocrisy.What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonWhy not just use typeof(a[0]) It does not matter if array is empty or not. Typeof does not actually evaluate its expression, just the type.
Aug 25 2020
On Tuesday, 25 August 2020 at 15:02:14 UTC, FreeSlave wrote:On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote:Wow, yet another way that should have been obvious! Thanks! --JonWhat's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --JonWhy not just use typeof(a[0]) It does not matter if array is empty or not. Typeof does not actually evaluate its expression, just the type.
Aug 25 2020