0

I am trying to write a class that will be appended with some function pointers.

This pointers will be called from another method of this class. I will be storing the function pointers on a void* vector so anything can go on a single vector, instead of a different vector for each type.

I intend to declare a different AppendCallback methods for any different function I need to call from inside the class, for example:

void MyClass:AppendCallback(void (*Callback)())
{
    _CallbackVector.push_back((void*)Callback);
    _IdVector.push_back(VoidID);
}

void MyClass:AppendCallback(void (*Callback)(uint32_t));
void MyClass:AppendCallback(void (*MyOtherClass::Callback)());
void MyClass:AppendCallback(void (*MyOtherClass::Callback)(uint32_t));

There will be a second vector that only contains identifiers to know what the void* points to, this is going to be assigned also on the AppendCallback Methods.

How can I cast the void pointer again to the function pointers for calling those functions?

Maybe something like this?

void MyClass::Service(uint32_t x)
{
    for(uint i = 0; i < _CallbackVector.size(); i++)
    {
        switch(_IdVector[i])
        {
            case VoidID: void(*_CallbackVector[i]()); break;
            case Uint32ID: void(*_CallbackVector[i](x)); break;
        }
    }
}

Edit:

Is this a proper way of casting from a void* to a function pointer?

10
  • Yes, you will have to store some sort of type information yourself. Commented Aug 9, 2019 at 18:39
  • 1
    iirc, in C++ there is no provision for storing a function pointer into a void*, nor for casting a void* back to a function pointer. It may work for your platform, but I think it is UB. You may want to add language-lawyer to this question. Commented Aug 9, 2019 at 18:44
  • 2
    This doesn’t address the question, but names that begin with an underscore followed by a capital letter (_CallbackVector, _IdVector) and names that contain two consecutive underscores are reserved for use by the implementation. Don’t use them in your code. Commented Aug 9, 2019 at 18:47
  • May be a dup: stackoverflow.com/questions/36645660/… Commented Aug 9, 2019 at 18:47
  • 3
    void* is not required to be large enough to hold a function pointer. Read about std::function. Commented Aug 9, 2019 at 18:51

1 Answer 1

3

That's not allowed in C++:

Converting a void* to a function pointer directly is not allowed (should not compile using any of the casts) in C++98/03. It is conditionally supported in C++0x (an implementation may choose to define the behavior and if it does define it then it must do what the standard says it should do. A void*, as defined by the C++98/03 standard, was meant to point to objects and not to contain function pointers or member pointers.

And again:

You can't.

You can cast a data pointer to void* and then back to the same pointer type you have started with. std::function is not a pointer type, so the cast is statically invalid, and it's not the same thing you have started with. You have started with a .target of type void()() but it's not a data pointer, it's a function pointer, so casting it to void and back is implementation-defined.

In your specific situation, you could try something like this:

class PointerToFunction {

};

template <typename Type>
class PointerToFunctionType : public PointerToFunction, std::function<Type> {
    public:
        using std::function<Type>::function; // I think this is the right syntax for this trick: https://softwareengineering.stackexchange.com/a/197901/342247


};

// Now, we can do this:

std::vector<PointerToType*> _CallbackVector;

Basically, we're using an inheritance trick similar to how boost::any/std::any (since C++17) is implemented to store any std::function in a pointer. The only issue is knowing how to convert it back. Doing this properly would depend on how you expected to convert that void* back to begin with (i.e., knowing its type), so I'll leave that part up to you.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.