从boost::any的指针调用可变进模板
Calling a variadic template from a pointer to boost::any
我正在尝试创建具有不同参数和返回类型的函数映射。所以,为了做到这一点,我通过stackoverflow搜索了很多,我想我得到了我需要的,但不是完全…
背景:从这篇文章中,pmr的答案是我需要的最准确的解决方案。因此,我已经将函数调用扩展为可变模板(我希望)。所以,这里是我的版本只是调用(其余的AnyCaller类是完全相同的):
template<typename Ret, typename ...Args>
Ret call(const std::string& s, Args&&... arg) {
// we have to assume that our users know what we are actually returning here
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(Args...)> >(a)(std::forward<Args>(arg)...);
}
它可以编译。现在,下面是我用来测试类的三个函数:
int foo() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
double foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return double(4.5); }
UINT foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
所以,第一个有int(void)的签名,第二个double(std::wstring),第三个double(std::wstring, std::wstring)。
现在,这是测试代码:
AnyCaller c;
c.add("foo1", std::function<int(void)>(foo));
c.add("foo2", std::function<double(std::wstring)>(foo2));
c.add("foo3", std::function<UINT(std::wstring, std::wstring)>(foo3));
c.call<int>("foo1");
c.call<double, std::wstring>("foo2", std::wstring(L"foo2!!!").data());
c.call<UINT, std::wstring, std::wstring>("foo3", std::wstring(L"foo3!!!").data(), std::wstring(L"---foo3!!!").data());
一切都很顺利:)
所以,这是正常工作的,我真正需要的是添加对函数成员的支持。基本上,我所做的就是创建一个类 a ,它具有完全相同的三个函数,还有一些用于测试的函数:
class A
{
public:
int foo() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
double foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return double(4.5); }
UINT foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
std::wstring foo4(VOID) { return std::wstring(L"foo4"); }
std::wstring foo5(std::wstring strData) { return (strData + L"--foo5"); }
VOID foo6(VOID) { ; }
};
但是我无法让这个工作。我的第一个问题是将指针添加到成员函数:
A a;
c.add("foo1", std::function<int(void)>(&A::foo)); // => Not valid
c.add("foo1", std::function<int(void)>(&a.foo)); // => Not valid
c.add("foo1", &a.foo); // => Not valid
c.add("foo1", a.foo); // => Not valid
c.add("foo1", ?????); //What in heaven goes here?
显然是从到的某种转换,但我无法想象…
当然,在那之后,我需要做实际的调用:
int nRet = c.call<int>("foo1");
感谢任何可以帮助的人:_)
PS:我不能做静态成员,如果这是一个解决方案…
PS2:我正在使用VS2013…
解决方案:
感谢@Kiroxas, @Praetorian和这篇文章的评论,我想出了一个不涉及可变模板的解决方案。
这些是我的测试类A
和B
:
class A
{
public:
int foo1() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
int foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return 5; }
int foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
};
class B
{
public:
std::wstring foo4(VOID) { return std::wstring(L"foo4"); }
std::wstring foo5(std::wstring strData) { return (strData + L"--foo5"); }
VOID foo6(VOID) { ; }
double foo7(std::wstring str1, int nNum)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += std::to_wstring(nNum);
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return double(3.1415);
}
};
这是将它们插入数组并调用它们的代码:)我理想的解决方案是将它们插入到映射中,因此,一旦我所有工作,我将再次更新!这个职位。
typedef struct
{
UINT ID;
std::wstring NAME;
boost::any Func;
} funcs;
funcs CallBackItems[] =
{
//From class A
{ 0, L"foo1", std::function<int(void)>(std::bind(&A::foo1, a)) },
{ 1, L"foo2", std::function<int(std::wstring)>(std::bind(&A::foo2, a, std::placeholders::_1)) },
{ 2, L"foo3", std::function<int(std::wstring, std::wstring)>(std::bind(&A::foo3, a, std::placeholders::_1, std::placeholders::_2)) },
//From class B
{ 3, L"foo4", std::function<std::wstring(void)>(std::bind(&B::foo4, b)) },
{ 4, L"foo5", std::function<std::wstring(std::wstring)>(std::bind(&B::foo5, b, std::placeholders::_1)) },
{ 5, L"foo6", std::function<void(void)>(std::bind(&B::foo6, b)) },
{ 6, L"foo7", std::function<double(std::wstring, int)>(std::bind(&B::foo7, b, std::placeholders::_1, std::placeholders::_2)) }
};
int nResult = -1;
std::wstring wstrResult = L"";
double dResult = 0.0;
//class A
nResult = boost::any_cast<std::function<int(void)>>(CallBackItems[0].Func)();
nResult = boost::any_cast<std::function<int(std::wstring)>>(CallBackItems[1].Func)(L"foo2");
nResult = boost::any_cast<std::function<int(std::wstring, std::wstring)>>(CallBackItems[2].Func)(L"foo", L"3");
//class B
wstrResult = boost::any_cast<std::function<std::wstring(void)>>(CallBackItems[3].Func)();
wstrResult = boost::any_cast<std::function<std::wstring(std::wstring)>>(CallBackItems[4].Func)(L"foo5");
boost::any_cast<std::function<void(void)>>(CallBackItems[5].Func)();
dResult = boost::any_cast<std::function<double(std::wstring, int)>>(CallBackItems[6].Func)(L"foo", 7);
A::foo(1|2|3)
是非静态成员函数,这意味着它们有一个隐式的第一个参数,一个指向它们被调用的对象实例的指针(this
指针)。您有两种选择,或者使用std::bind
来绑定要调用成员函数的对象,或者稍后在call()
时传递指向该对象的指针。
我用一个可变模板版本替换你的两个call
重载
template<typename Ret, typename... T>
Ret call(const std::string& s, T&&... arg) {
// we have to assume that our users know what we are actually returning here
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(T...)> >(a)(std::forward<T>(arg)...);
}
选项1:使用std::bind
A a;
AnyCaller c;
c.add("foo1", std::function<int()>(std::bind(&A::foo1, &a)));
c.add("foo2", std::function<double(std::wstring)>(
std::bind(&A::foo2, &a, std::placeholders::_1)));
c.call<int>("foo1");
c.call<double>("foo2", std::wstring(L"Calling foo2"));
选项2:调用函数时传递对象指针。注意,在本例中,std::function
的类型是不同的。
A a;
AnyCaller c;
c.add("foo1", std::function<int(A*)>(&A::foo1));
c.add("foo2", std::function<double(A*, std::wstring)>(&A::foo2));
c.call<int>("foo1", &a);
c.call<double>("foo2", &a, std::wstring(L"Calling foo2"));
第二个选项在VS2013上不起作用。
两个选项的实时演示
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 创建一个函数的 Python 绑定,返回指向带有 boost 的向量的指针
- boost::spirit指针属性是用nullptr初始化的吗?
- 序列化和反序列化boost共享指针
- C++ 从 Boost object_pool构造的指针的 Boost 二进制序列化
- 通过 Boost Python 在C++对象之间传递共享指针的隔离错误
- 使用 boost::序列化将派生类指针序列化为向量时出现问题
- 获取“boost::文件系统::p ath”字符指针时出现问题
- 将 boost::function 与指向派生类的共享指针的参数一起使用
- 如何将Protobuf的Boost :: Shared_ptr指针传递给功能
- BOOST-ASIO ASYNC_RECEIVE_FROM功能超载问题( 动态指针)
- boost::compute,将指针传递给闭包
- 如何使用boost::graph dijkstra的算法,如果顶点属性是指针?
- Boost Python:指针设置为空
- 将 boost::object_pool 与矢量一起使用时指针无效
- Boost ::与指针与值的混淆
- boost::shared_ptr来自指针
- 如何从“boost::function”中获取 C 指针(如 'var (*)(vo
- 指向方法的指针/传递这个指针/ boost::bind
- 将Base1指针转换为Base2指针(boost shared_ptr)