digitalmars.D.learn - What is the proper way to outline static-if-conditions ?
- Elmar (54/54) Oct 10 2021 Hey D people.
- Elmar (3/3) Oct 10 2021 PS: the title is a misnomer. `is(T : P*, P) && isStaticArray!P`
- drug (24/24) Oct 10 2021 You just need to check if T is a pointer:
- Elmar (2/27) Oct 10 2021 Wow, this is a fine solution. I gonna use it, thank you :-) .
Hey D people. Currently in my project I have worked on a unified type interface for all arrays which requires fixed-size arrays to be stored as pointer (in correspondence to dynamic and associative arrays) and allow them being allocated with any selected allocator. There can be code like this: ```d enum isPointedStaticArray(T) = (is(T : P*, P) && .isStaticArray!P); //... static if (.isPointedStaticArray!T) { // ... } ``` It won't compile when the argument of `isPointedStaticArray()` is NO pointer. The compiler complains, about **`P` being undefined**. What is the best workaround for this? It's crazy. I can reverse the problem that it only fails if the argument IS a pointer: ```d enum isPointedStaticArray(T) = (){ enum condition = `is(`~T.stringof~` : P*, P) && .isStaticArray!P`; static if (__traits(compiles, mixin(condition)) ) return mixin(condition); // "P already defined" error else return false; }(); ``` Types defined in `__traits(compiles, ...)` are emitted to the outside?! Okay, this is my current workaround: ```d enum isPointedStaticArray(T) = (){ static if (is(T : P*, P)) return .isStaticArray!(P); else return false; }(); // ... static if (isPointedStaticArray!T) { } ``` for outlining an expression `is(...) && ...` Is there a simpler way in D to do this? If there only would be a `&&&` short circuit operator which doesn't compile the right side if the left side wouldn't compile to true. Did someone already had the idea of a `static-try-catch` which catches compilation errors?
Oct 10 2021
PS: the title is a misnomer. `is(T : P*, P) && isStaticArray!P` doesn't either compile when inlined because `P` is not defined when not matched.
Oct 10 2021
You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length
Oct 10 2021
On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote:You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its lengthWow, this is a fine solution. I gonna use it, thank you :-) .
Oct 10 2021
On Sunday, 10 October 2021 at 14:36:50 UTC, Elmar wrote:On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote:Well, I just wondered why your code would compile and mine wouldn't. The `version(all)` variant will not compile on my computer with `rdmd` because `PointerTarget` only allows pointers. But the 2nd one will compile. The `is()` expression catches the compilation error which is nice. This is sufficient: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` It would be nice if one could use pattern-matching for it in D. Is this possible? ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); enum isPointedStaticArray(X : else) = false; ```You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its lengthWow, this is a fine solution. I gonna use it, thank you :-) .
Oct 10 2021
On Sunday, 10 October 2021 at 15:01:17 UTC, Elmar wrote:```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); ````isStaticArray` is a good example that makes me ask how to outline an `is()` expression without losing the error catching semantics of the inlined `is()` expression.
Oct 10 2021
On 10.10.2021 18:01, Elmar wrote:Well, I just wondered why your code would compile and mine wouldn't. The `version(all)` variant will not compile on my computer with `rdmd` because `PointerTarget` only allows pointers.It depends on compiler version. This variant is compiled on version 2.092.1 and aboveBut the 2nd one will compile. The `is()` expression catches the compilation error which is nice. This is sufficient: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` It would be nice if one could use pattern-matching for it in D. Is this possible? ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); enum isPointedStaticArray(X : else) = false; ```As I know it's impossible, but you can use a regular template: ```d template isPointedStaticArray(T) { static if (isPointer!T) enum isPointedStaticArray = isStaticArray!(PointerTarget!T); else enum isPointedStaticArray = false; } ``` https://run.dlang.io/is/lR7feP this compiles from 2.086.1 and above
Oct 10 2021
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote:As I know it's impossible, but you can use a regular template: ```d template isPointedStaticArray(T) { static if (isPointer!T) enum isPointedStaticArray = isStaticArray!(PointerTarget!T); else enum isPointedStaticArray = false; } ``` https://run.dlang.io/is/lR7feP this compiles from 2.086.1 and aboveThat's indeed close to pattern matching and is probably the best answer :-) .
Oct 10 2021
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote:If anyone is interested in pattern matching, someone provides a package "dpmatch" which uses PEG (some parsing grammer which is implemented in D) to achieve Haskel-style pattern matching, yet for sum-type definitions only. And they use GC + interfaces. Hence it cannot be used with BetterC. Sumtypes can also be created with the `sumtype` package which uses D's delegate literals for pattern matching.It would be nice if one could use pattern-matching for it in D. Is this possible?As I know it's impossible, but you can use a regular template: ...
Oct 10 2021