从 boost::any 恢复函数指针
我想使用 boost::any 来存储异构函数指针。当我尝试使用 boost::any_cast 重新转换为函数指针时出现异常。
我想做的事情是否被允许?
.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);
}
----编辑----
好的,你是对的,之所以这样,是因为 foo 是一个类成员函数。
意思是:
void MyClass::foo();
myInfo.functionPointer = &MyClass::foo;
所以我需要输入:
typedef void(MyClass::*voidClassFunction)(void);
voidClassFunction myVoidFunction = boost::any_cast<voidClassFunction>(functionList[0].functionPointer);
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
绝对地。只要您将其精确地转换回您指定的类型即可。
这就是你的问题。你不知道。
foo2
不是voidFunction
。因此,您不能将其转换为一。boost::any
的目的是保证void*
要么根据 C++ 标准正确工作,要么抛出异常。 C++ 标准允许将任何(非成员)指针类型转换为void*
。它还允许将void*
转换回类型,前提是提供的类型与原始类型完全相同。如果不是,欢迎使用未定义的行为。boost::any
的存在是为了通过使用void*
存储类型信息来防止未定义的行为。当您尝试将某些内容转换为错误的类型时,它会正确地抛出异常。正如你在这里所做的那样。boost::any
并不是一种假装类型不存在以及假装可以将任何东西变成其他东西的方法。它只是一个类型安全的无类型容器。您仍然需要知道您实际放在那里的是什么。无法存储具有任意参数列表的函数列表并使用相同的参数列表调用它们。用户必须提供具有您期望的正确参数列表的函数或函子。 boost::bind 是一种使函数/函子适应特定参数列表的方法,但用户必须显式使用它。
您能做的最好的事情就是拥有一个您接受的特定函数参数集的列表,并将其存储在
boost::variant
对象中。您可以使用访问者来确定要调用哪个特定函数。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 avoidFunction
. Therefore, you cannot cast it to one.The purpose of
boost::any
is to have avoid*
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 avoid*
. It also allows conversion of avoid*
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 thevoid*
. 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.