Best way of checking for a templated function instantiation

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Aug 10 07:02:05 PDT 2016


On Wednesday, August 10, 2016 12:36:14 Arafel via Digitalmars-d-learn 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!"-"));
> }
> ---

I'd advise against checking for opBinary in general, because it'll only work
with user-defined types, whereas a built-in type may define the operator.
It's usually better to test that the operator works rather than that
opBinary exists.  So, you end up with checks like __traits(compiles, lhs +
rhs) or __traits(compiles, T.init + T.init). If you're picky about the
return type, you can do stuff like __traits(compiles, T t = T.init + T.init)
(that might require braces around the statement along with a semicolon; I
don't remember). If you test for it enough, you can create an eponymous
template that wraps the test so that you just have to do something like
hasAdd!T or hasBinaryOp!("+", T). That's basically what you get with traits
like isInputRange. They're eponymous templates that wrap tests that use
is(typeof(...)) or __traits(compiles, ...) to test that a particular block
of code or expression compiles, but wrapping that in an eponymous template
makes it more idiomatic and makes it so that you don't have to duplicate the
implementation of the check everywhere (which is important if the check
isn't simple).

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list