0

So for this function:

template<typename T>
T popObject(ScriptObject obj) { //Preforms a cast from void* on each to its type.
    assert(obj.getType() == std::type_index(typeid(T))); //Ensure type Safety.
    return obj.get<T>();
}

template <typename C, typename...Args>
    void bind(const char* name, C* context, void(C::* function)(Args...)) {
        std::vector<std::type_index> arguments = { std::type_index(typeid(Args))... };
        auto functor = [](void* func,void* contex, std::vector<ScriptObject> stack) {
            std::size_t idx = 0;
            //Call class context -> function (Args...)
        };
        _functions[name] = new BoundFunction(functor, void_cast(function), context, arguments);
    }

I'm unsure of the syntax for calling the member function.

Iv tried:

union MF{
    void(C::* pf)(Args...);
    void* p;
} mf;
mf.p = func;
contex->*(mf.pf)(popObject<Args>(stack[idx++])...);

Which does not compile, Stating: "Does not evaluate to a function taking 1 Arguments."

Tried std::invoke, But I Don't know how to Specify the Member function Signature for arg1.

So If i have a reference to the member function, And a reference to the instance of the class, As well as the template information to Derive type information. How do I call the Classes member function?

Steven Venham
  • 600
  • 1
  • 3
  • 18
  • Shot in the dark, still looking it over, have you tried `popObject`? Or changing `static_cast(contex).*` to `static_cast(contex)->`? Also why are you casting `pf` to a type it already is? – The Floating Brain May 26 '20 at 00:11
  • 1
    `(context->*(mf.pf))(...)`. First, it's `->*` not `.*`, since you have a pointer on the left. Second, note the parentheses around `context->*(mf.pf)` part. – Igor Tandetnik May 26 '20 at 00:16
  • @TheFloatingBrain Thats a no go, Args... Would evaluate to template with each of the arguments, I still Want popObject to run on each Individual Argument. And -> only works if the member function name is known. – Steven Venham May 26 '20 at 00:16
  • @StevenVenham Sorry misread, but you should take a look at Igor's comment. Also if your function pointer pf takes in `Args...` does `popObject` return the type it gets from unfolding the pack? – The Floating Brain May 26 '20 at 00:21
  • 1
    Ok So changed to static_cast(ctx)->*(mf.pf)(popObject(stack[idx++])...); Good call on the extra static cast @TheFloatingBrain And Iv changed it to ->* Igor – Steven Venham May 26 '20 at 00:21
  • Still having the problem? – The Floating Brain May 26 '20 at 00:23
  • Yep Still gives Same "Does not evaluate to a function taking 1 Arguments." Error – Steven Venham May 26 '20 at 00:24
  • @StevenVenham okay, so two questions, 0: does `popObject` return the same type it takes in as its template parameter? 1: Your code currently looks like `context->*(mf.pf)(popObject(stack[idx++])...)` ? – The Floating Brain May 26 '20 at 00:31
  • Ill Update the question – Steven Venham May 26 '20 at 00:33
  • Again - put a pair of parentheses around `static_cast(ctx)->*(mf.pf)` part. `->*` operator has lower precedence than function call operator. – Igor Tandetnik May 26 '20 at 00:42
  • OHHH thats what you ment, @IgorTandetnik Thanks, Ill Post An answer crediting you. – Steven Venham May 26 '20 at 00:46
  • A couple issues you should consider: argument evaluation order is implementation-defined, so your arguments may not appear in the correct order, and pointers to member function can be wider than void*, so your punning to void* is potentially problematic. – Jeremy Roman May 26 '20 at 00:49
  • @JeremyRoman Any ideas Of solutions for that? Is there a way to Ensute the Peramaters are packed in a spesific order, And think i can use a DWORD? – Steven Venham May 26 '20 at 00:54
  • For the former, there are multiple approaches, but I'd probably pop the whole lot as a single operation into an array of ScriptObject, and then do only the casts in the parameter expansion. DWORD is no larger than void* (and PMFs can vary in size by type anyway). If you insist on fixing the size of your capture block, at least use memcpy and assert that the size suffices. Or if your callers always pass a fixed PMF you could have them pass a (captureless) lambda instead, which decays into a fixed size function ptr. – Jeremy Roman May 26 '20 at 00:59
  • As far as I know, there is no guarantee that this code will works as member pointer might be larger than a void and the actual representation might depend on things like inheritance (none, single, multiple, virtual) and if the function are virtual or not. At least, any assumption should validated either at compile-time or run-time. – Phil1970 May 26 '20 at 02:05

1 Answers1

1

Thanks @Igor Tandentnik

Final Solution was:

(static_cast<C*>(ctx)->*(mf.pf))(popObject<Args>(stack[idx++])...);

As Igor pointed out, it needed to be ->* instead of .*, and added parenthesis, as -> has a lower priority then the Function call operator.

Also, thanks @TheFloatingBrain for pointing out the extra static_cast

Steven Venham
  • 600
  • 1
  • 3
  • 18
  • I would wish to try your solution as well. Can you give a working example? Some of the functions are missing and not sure what they intend to do/check. – schanti schul Aug 21 '22 at 09:59