www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Static if a Function Exists

reply Jonathan Levi <catanscout gmail.com> writes:
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.
Apr 02 2020
parent reply WebFreak001 <d.forum webfreak.org> writes:
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
Apr 03 2020
parent Jonathan Levi <catanscout gmail.com> writes:
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.
Apr 04 2020