Thread overview
What is the proper way to outline static-if-conditions ?
Oct 10, 2021
Elmar
Oct 10, 2021
Elmar
Oct 10, 2021
drug
Oct 10, 2021
Elmar
Oct 10, 2021
Elmar
Oct 10, 2021
Elmar
Oct 10, 2021
drug
Oct 10, 2021
Elmar
Oct 10, 2021
Elmar
October 10, 2021

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:

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:

	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:

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?

October 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.

October 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

October 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 length

Wow, this is a fine solution. I gonna use it, thank you :-) .
October 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:

>

You just need to check if T is a pointer:

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

Wow, this is a fine solution. I gonna use it, thank you :-) .

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:

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?

	enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X);
	enum isPointedStaticArray(X : else) = false;
October 10, 2021

On Sunday, 10 October 2021 at 15:01:17 UTC, Elmar wrote:

>
enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N);
	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.

October 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 above

> 
> 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;
> ```
> 

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
October 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 above

That's indeed close to pattern matching and is probably the best answer :-) .
October 10, 2021
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote:
>> 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:
> ...

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.