Thread overview
Static if a Function Exists
Apr 03, 2020
Jonathan Levi
Apr 03, 2020
WebFreak001
Apr 05, 2020
Jonathan Levi
April 03, 2020
I am trying to make a templated function for any arguments which will work for another.

Like this:
```
class Cls {
    auto opBinary(string op, T)(T b)
    if (__traits(compiles, opBinaryImpl!op(this, b)))
    {
        return opBinaryImpl!op(this, b);
    }
}

auto opBinaryImpl(string op, T)(Cls a, T b)
if (isNumeric!T)
{
    // . . .
}
```

Here I use `__traits(compiles)` but if `opBinaryImpl` has a compile error in the body than opBinary will claim it does not work.

I am looking for something like `__traits(signatureMatch,...)`.

Using std.traits.Parameters does not work because it does not work on templates nor does it work with overloading.

April 03, 2020
On Friday, 3 April 2020 at 01:03:01 UTC, Jonathan Levi wrote:
> I am trying to make a templated function for any arguments which will work for another.
>
> Like this:
> ```
> class Cls {
>     auto opBinary(string op, T)(T b)
>     if (__traits(compiles, opBinaryImpl!op(this, b)))
>     {
>         return opBinaryImpl!op(this, b);
>     }
> }
>
> auto opBinaryImpl(string op, T)(Cls a, T b)
> if (isNumeric!T)
> {
>     // . . .
> }
> ```
>
> Here I use `__traits(compiles)` but if `opBinaryImpl` has a compile error in the body than opBinary will claim it does not work.
>
> I am looking for something like `__traits(signatureMatch,...)`.
>
> Using std.traits.Parameters does not work because it does not work on templates nor does it work with overloading.

maybe not the optimal solution because stringof isn't properly defined, but currently I don't think there is a better way than:

template matchesTemplateConstraints(alias fn, Args...)
{
    enum def = fn.stringof;
    // private void testFun(string op, T)(Cls a, T b) if (isNumeric!T) {}
    mixin("private void testFun" ~ def[def.indexOf('(') .. $] ~ " {}");

    enum matchesTemplateConstraints = __traits(compiles, testFun!Args);
}

void main()
{
    // true
    pragma(msg, matchesTemplateConstraints!(opBinaryImpl, "+", int));

    // false
    pragma(msg, matchesTemplateConstraints!(opBinaryImpl, "+", string));
}

You can also static foreach over __traits(getOverloads, mixin(__MODULE__), "opBinaryImpl", true) if you have multiple templates of same name
April 05, 2020
On Friday, 3 April 2020 at 07:08:03 UTC, WebFreak001 wrote:
> maybe not the optimal solution because stringof isn't properly defined, but currently I don't think there is a better way than:
>
> template matchesTemplateConstraints(alias fn, Args...)
> {
>     enum def = fn.stringof;
>     // private void testFun(string op, T)(Cls a, T b) if (isNumeric!T) {}
>     mixin("private void testFun" ~ def[def.indexOf('(') .. $] ~ " {}");
>
>     enum matchesTemplateConstraints = __traits(compiles, testFun!Args);
> }
>
> void main()
> {
>     // true
>     pragma(msg, matchesTemplateConstraints!(opBinaryImpl, "+", int));
>
>     // false
>     pragma(msg, matchesTemplateConstraints!(opBinaryImpl, "+", string));
> }
>
> You can also static foreach over __traits(getOverloads, mixin(__MODULE__), "opBinaryImpl", true) if you have multiple templates of same name

I will try that out, thanks.  I do have overloads, and somehow I missed the existence of `__traits(getOverloads)`.


Ah, I see, take the string of the function code (didn't know you could do that...) and create a local duplicate without the body included.  Hacky, but a workable solution if D does not have anything better.