On Wednesday, 10 August 2016 at 12:36:14 UTC, Arafel wrote:
Hi,
I'm trying to check at compilation time if a given type
implements some operator (let's assume it's '+' in this case),
without caring about the type of the parameters it accepts.
Since operator overloading is expressed in D through templated
functions, what is the preferred way of checking if a template
is / can be instantiated with a given parameter list?
So far I've come with a solution using __trait(compiles, ...),
but perhaps it's not 100% reliable -I'm no expert in template
wizardry-, or there are better options. I also tried with
hasMember, but it apparantly only shows that "opBinary" is
indeed present, but nothing more:
---
void main() {
struct S {
int opBinary(string op)(int i) if (op == "+") {
return 0;
}
}
static assert(__traits(compiles, S.opBinary!"+"));
static assert(!__traits(compiles, S.opBinary!"-"));
}
---
__traits(compiles) is pretty much the only way to do it. For
example, if you want to check that S supports opBinary!"+"(int):
static assert(__traits(compiles, auto _ =
S.init.opBinary!"+"(int.init));
And if you want to check that the return type is int or
implicitly converts to int, you can change the `auto _ = ...` to
`int _ = ...`. However, if you want to be more explicit about it,
you can do the following:
import std.traits;
static assert(is(ReturnType!(S.opBinary!"+") == int)); //Change
to `... : int` for implicit conversion checking