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

Adam D. Ruppe destructionator at gmail.com
Tue Sep 29 01:19:48 UTC 2020


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!!

That's a nested function and thus actually has a hidden argument. 
Of course, you could add `static` to it if it doesn't use other 
local variables, then it will work again.

But to handle nested functions, you can simply add a check for 
isNested too.


Bringing me to this:

-----
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 .. $]);
}

// I think the above covers all the cases, what follows
// are just some tests of various situations.

struct Foo
{
   bool isValid(int a)
   {
     return a > 0;
   }

   struct Bar {
         void bar() {}
}

Bar bar;
}

int add3(int a, int b)
{
   return a + b;
}

class A {
         void test() {}

         int item;

         class B {
                 void other(int arg) { import std.stdio; 
writeln(item, " nested ", arg); }
         }

         static class C {
                 void cool(string) {}
         }
}

void main() {

         auto a = new A;
         a.item = 30;
         invoke!(A.C.cool)(new A.C, "ok");
         invoke!(A.B.other)(a.new B, 6);
         invoke!(A.test)(a);
         invoke!(Foo.Bar.bar)(Foo.Bar.init);

         int add(int a, int b)
         {
           return a + b;
         }
         int add2(int a, int b)
         {
           return a + b;
         }


         assert(invoke!add(1, 2) == 3);
         assert(invoke!add2(1, 2) == 3);
         assert(invoke!add3(1, 2) == 3);

         auto foo = Foo();
         assert(invoke!(Foo.isValid)(foo, 3));
}
-------


More information about the Digitalmars-d-learn mailing list