Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Rekel via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 15:00:24 UTC, Paul Backus wrote:

On Tuesday, 6 July 2021 at 14:43:26 UTC, Rekel wrote:
Is there any reason the function call in the alias is 
acceptable? I would imagine the () part would actually require 
2 parameters.


You're right, it does; that was a mistake on my part. It should 
work with `Lhs.init` and `Rhs.init` as arguments.


Hmm . . . doing that ironically brings me back to using:

```d
alias ResultType(Lhs, string op, Rhs) = typeof(mixin("Lhs.init" ~ 
op ~ "Rhs.init"));


auto opBinary(string op, R:
T2[], T2)(R right) const if (is(ResultType!(T, op, T2))) {
Vec!(ResultType!(T, op, T2), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right[i];");
}
return result;
}
```

Kind of ironic this is basically an alias of my old solution.
Strangely enough the nanF issue went away though, I guess I 
misinterpreted this.

Thanks for your help anyway 


Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:43:26 UTC, Rekel wrote:
Is there any reason the function call in the alias is 
acceptable? I would imagine the () part would actually require 
2 parameters.


You're right, it does; that was a mistake on my part. It should 
work with `Lhs.init` and `Rhs.init` as arguments.


Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Rekel via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:27:35 UTC, Paul Backus wrote:
Instead of having the template evaluate to a `bool`, have it 
evaluate to the type of the result:


```d
alias ResultType(Lhs, string op, Rhs) =
typeof(((Lhs lhs, Rhs rhs) => mixin("lhs", op, "rhs"))());

static assert(is(ResultType!(int, "+", double) == double));
static assert(is(ResultType!(string, "~", string) == string));
static assert(!is(ResultType!(string, "+", int))); // no valid 
result type

```

Then you can use `is()` in the template constraints to check 
whether the operation is supported:


```d
auto opBinary(string op, Rhs: T2[], T2) const
if (is(ResultType!(T, op, T2)))
{
Vec!(ResultType!(T, op, T2), L) result;
// etc.
}
```


Oh that's neat, thanks.
I guess that would make it:
```d
auto opBinary(string op, R)(R right) const if (is(ResultType!(T, 
op, R))) {

Vec!(ResultType!(T, op, R), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right;");
}
return result;
}
```

I guess I'll just have to take the result definition for what it 
is. At least the return type can use auto, haha. Imagine using 
ResultType!(T, op, R) thrice...


Is there any reason the function call in the alias is acceptable? 
I would imagine the () part would actually require 2 parameters.




Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:12:48 UTC, Rekel wrote:
I recently found __traits(compiles, ...) can be used in 
template constraints.
(I first used `is(mixin("T.init"~op~"T2.init"))` but this cause 
problems related to nanF)


However I'm wondering if there is an easier way to do what I'm 
currently doing, especially since using typeof inside the 
result declaration is quite cumbersome. This is a bigger 
problem in my less-simplified code (using matrices), where it 
starts getting slightly unreadable.
It also assumes the presence of .vec[0] (not necessarily a 
problem here but it seems like a codesmell)


Simplified:
```d
template supported(A, string op, B) {
const bool supported = __traits(compiles, (A a, B b) {
mixin("return a" ~ op ~ "b;");
});
}
```


Instead of having the template evaluate to a `bool`, have it 
evaluate to the type of the result:


```d
alias ResultType(Lhs, string op, Rhs) =
typeof(((Lhs lhs, Rhs rhs) => mixin("lhs", op, "rhs"))());

static assert(is(ResultType!(int, "+", double) == double));
static assert(is(ResultType!(string, "~", string) == string));
static assert(!is(ResultType!(string, "+", int))); // no valid 
result type

```

Then you can use `is()` in the template constraints to check 
whether the operation is supported:


```d
auto opBinary(string op, Rhs: T2[], T2) const
if (is(ResultType!(T, op, T2)))
{
Vec!(ResultType!(T, op, T2), L) result;
// etc.
}
```