Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward member function to static method

Context

Basically I need to have a const void *const for a member function, because that has to be passed to a third party library (which means I cannot use bind, function, etc). Since that seems to be impossible, I wanted to do the next best thing and map a member function to a static forwarding method, which I can then get the pointer for (passing this as first argument).

Question

I have a lot of functions that I need to register, with different signatures, so I would like to have a nice solution that allows me to convert a signature of a member function into a static method signature (passing this as an argument of course) - which I can then cast to a const void* const. So basically I want to do something like this:

So basically:

struct Foo
{ 
    MyType Bar(int a);
};

template <typename Ret, typename This, Ret(This::*Func)()>
struct CallWrap0
{
    static Ret &&Call(This* thisPtr)
    {
        return thisPtr->(*Func)();
    }
};

int Main()
{
    const void * const memberFunction = &(CallWrap0<MyType, Foo, Foo::Bar>()::Call);
    // etc.
}

The problem with this solution is that - even though it works - it's not very nice, because I have to explicitly tell the compiler the types. I'm looking for a solution where the compiler can fill in all the plumbing automagically.

I've been attempting to work around this with a helper function, so far without luck:

template <class Ret, class T, class... Args>
const void* const FunctionPtr(Ret (T::*function)(Args... args))
{
    // not sure... function is not a template, so this would require a class instance
    // which is not possible due to the ext. library constraints.
}
like image 722
atlaste Avatar asked Sep 15 '15 07:09

atlaste


People also ask

What is a static member function?

Static member functions. In the previous lesson on 11.13 -- Static member variables, you learned that static member variables are member variables that belong to the class rather than objects of the class. If the static member variables are public, we can access them directly using the class name and the scope resolution operator.

What is the difference between private static member and static method?

A private static member can be access using a public member function A static method is a method that can only access static data member of class. It cannot access non static data member of that class

Can We do better with member functions?

We can do better. It turns out that we can also make functions static. Like static member variables, static member functions are not attached to any particular object. Here is the above example with a static member function accessor:

How to access static member variables directly from main ()?

If the static member variables are public, we can access them directly using the class name and the scope resolution operator. But what if the static member variables are private? Consider the following example: In this case, we can’t access Something::s_value directly from main (), because it is private.


1 Answers

#include <utility>

template <typename T, T t>
struct CallWrap;

template <typename Ret, typename This, typename... Args, Ret(This::*Func)(Args...)>
struct CallWrap<Ret(This::*)(Args...), Func>
{
    static Ret Call(This* thisPtr, Args... args)
    {
        return (thisPtr->*Func)(std::forward<Args>(args)...);
    }
};

int main()
{
    auto f = &CallWrap<decltype(&Foo::Bar), &Foo::Bar>::Call;
}

DEMO


For MSVC, which fails to compile the above solution, try the below code:

template <typename T>
struct CallWrap;

template <typename Ret, typename This, typename... Args>
struct CallWrap<Ret(This::*)(Args...)>
{
    template <Ret(This::*Func)(Args...)>
    struct Function
    {
        static Ret Call(This* thisPtr, Args... args)
        {
            return (thisPtr->*Func)(std::forward<Args>(args)...);
        }
    };
};

int main()
{
    auto f = &CallWrap<decltype(&Foo::Bar)>::Function<&Foo::Bar>::Call;
}

DEMO 2

like image 151
Piotr Skotnicki Avatar answered Sep 27 '22 23:09

Piotr Skotnicki