Question

I want to use boost::any to store heterogeneous function pointers. I get an exception when I try to use boost::any_cast to recast to the function pointer.

Is what I want to do even allowed?

.h:

typedef void(*voidFunction)(void);
struct functionInfo{
       CString    functionName;
       boost::any functionPointer;
};
void foo();
int foo2(int a);

.cpp

void foo()
{
  ;//do something
}

int foo2(int a)
{
  ;//do something
}

void main()
{
    vector<functionInfo> functionList;
    functionInfo myInfo;
    myInfo.functionName = _T("foo");
    myInfo.functionPointer = &foo;
    functionList.push_back(myInfo);
    myInfo.functionName = _T("foo2");
    myInfo.functionPointer = &foo2;
    functionList.push_back(myInfo);

    voidFunction myVoidFunction = boost::any_cast<voidFunction>(functionList[0].functionPointer);

}

----EDIT----

Ok, you are right, the reason why it acted like this is because foo is a class member function.

Meaning:

void MyClass::foo();

myInfo.functionPointer = &MyClass::foo;

so I needed to typedef:

typedef void(MyClass::*voidClassFunction)(void);
voidClassFunction myVoidFunction = boost::any_cast<voidClassFunction>(functionList[0].functionPointer);
Was it helpful?

Solution

Is what I want to do even allowed?

Absolutely. As long as you cast it back to exactly the type you gave it.

And that's your problem. You don't. foo2 is not a voidFunction. Therefore, you cannot cast it to one.

The purpose of boost::any is to have a void* that is guaranteed to either work correctly according to the C++ standard or throw an exception. The C++ standard allows the conversion of any (non-member) pointer type to a void*. It also allows conversion of a void* back to a type, provided that the type being provided is exactly the same type as the original. If it's not, welcome to undefined behavior.

boost::any exist to prevent undefined behavior by storing type information with the void*. It will rightly throw an exception when you attempt to cast something to the wrong type. As you do here. boost::any is not a way to pretend that types don't exist and to pretend that you can turn anything into something else. It's just a type-safe typeless container. You still need to know what you actually put there.

There is no way to store a list of functions with arbitrary argument lists and call them with the same argument list. The user must provide a function or functor with the right argument list that you expect. boost::bind is a way to adapt a function/functor for a particular argument list, but the user must explicitly use it.

The best you can do is have a list of specific function parameter sets that you accept, stored in a boost::variant object. You can use a visitor to figure out which particular function to call.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top