0
votes
size_t getAddress(F f) {
    typedef void (fnType)(Ts...);
    fnType ** fnPointer = f.template target<fnType*>();
    if (fnPointer == nullptr) { //Must be member function.
        //Code to get address of member function pointer
    }
    return (size_t)*fnPointer;
}

This function works fine for function pointers, but when I try to throw a bound Member function into the mix everything goes south.

I think this is because I template the function pointer as my normal function pointer type. But with a bound member function through std::bind this conversion fails.

I use this in my comparison operator for finding and removing functions from a vector.

EventObject<Ts...>& operator-=(const F& rhs) {
    int i = 0;
    for (auto const& value : callbacks) {
        if (getAddress(rhs) == getAddress(value)) {
            erase(i);
            break;
        }
        i++;
    }
    return *this;
}

Google has failed me. I also imagine that this function will work for lambdas, sorta. As long as the compiler tries to optimize and combine similar lambda expressions.

So how do I get the address of a member function pointer through bind? Or is there a more optimal way? (Besides naming) Perhaps, should I wrap my function in a macro to store the enumerated type for comparisons instead?

Class information for reference:

template <typename...Ts>
class EventObject{
public:
    typedef std::function<void(Ts...)> F;
    typedef std::vector<F> CallBack;
    Callback callbacks;
1
This looks like an XY type of question.darune
It's hard to understand what's going on in your code, but the problem seems to be that it's impossible to convert any kind of stateful functors (stateful lambdas, member functions bound with bind, and so on) to function pointers. Use std::functions instead of function pointers.HolyBlackCat

1 Answers

1
votes

You should switch to using std::function instead (update: it turns out you did already). std::function is a general-purpose polymorphic function wrapper that will accept raw function pointers, binds, etc. That way you have a standardized way to compare, which you need to pull off somehow but std::function has ways to inspect the target, etc. : https://en.cppreference.com/w/cpp/utility/functional/function

Your signature becomes:

EventObject<Ts...>& operator-=(const std::function<R(Args...)>& rhs) {

Update: the issue with your target extraction is that you provide the signature of a plain function as the template argument - this will not work for the more 'advanced' function objects, binds etc. you have to provide the correct type so that:

target_type() == typeid(T)

see https://en.cppreference.com/w/cpp/utility/functional/function/target for more information and some relevant examples