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:
template supported(A, string op, B) {
const bool supported = __traits(compiles, (A a, B b) {
mixin("return a" ~ op ~ "b;");
});
}
struct Vec(T, uint L) {
T[L] vec;
alias vec this;
auto opBinary(string op, R:
T2[], T2)(R right) const if (supported!(T, op, T2)) {
Vec!(typeof(mixin("this[0]" ~ op ~ "right[0]")), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right[i];");
}
return result;
}
auto opBinary(string op, R)(R right) const if (supported!(T, op, R)) {
Vec!(typeof(mixin("this[0]" ~ op ~ "right")), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right;");
}
return result;
}
}
void main(string[] args) {
Vec!(float, 4) v = Vec!(float, 4)([0, 1, 2, 3]);
auto w = v * 2.0;
auto x = v + v;
auto y = v + [1, 1, 1, 1];
pragma(msg, typeof(w)); // prints "Vec!(double, 4u)"
pragma(msg, typeof(x)); // prints "Vec!(float, 4u)"
pragma(msg, typeof(y)); // prints "Vec!(float, 4u)"
}