How to write a counterpart to C++ std::invoke that works with both free functions and methods?

60rntogo 60rntogo at gmail.com
Sun Oct 4 08:55:44 UTC 2020


On Tuesday, 29 September 2020 at 01:19:48 UTC, Adam D. Ruppe 
wrote:
> On Sunday, 27 September 2020 at 05:22:36 UTC, 60rntogo wrote:
>> How would I check if it is actually a free function?
>>
>> but this doesn't even compile since I defined add inside my 
>> main function
>
> aaaaah that's not a free function!!

OK, I see. That makes sense I suppose. Thanks for putting this 
together, but I'm afraid that I managed to break it again and 
this time it is really baffling.

---
module foo;

auto invoke(alias fun, Args...)(Args args)
{
   static if(__traits(isStaticFunction, fun) || __traits(isNested, 
fun))
     return fun(args);
   else
     return __traits(child, args[0], fun)(args[1 .. $]);
}

unittest
{
   import std : approxEqual;
   assert(invoke!approxEqual(2.0, 2.001));
}
---

This gives me these errors:

---
source/foo.d(6,48): Error: aggregate or function expected instead 
of approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 
0.01, V maxAbsDiff = 1e-05)
source/foo.d(9,41): Error: template std.math.approxEqual cannot 
deduce function from argument types !()(double), candidates are:
/usr/include/dmd/phobos/std/math.d(8479,6):        approxEqual(T, 
U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 
1e-05)
source/foo.d(15,28): Error: template instance 
foo.invoke!(approxEqual, double, double) error instantiating
---

Confusingly, these errors disappear if I include the unit test in 
my main file (i.e., just add it to the code you posted) rather 
than foo.d or if I use a function like add defined in the module 
instead of imported approxEqual. Any ideas?


More information about the Digitalmars-d-learn mailing list