[英]Storing boost function
I have to store a list of different boost::function objects. 我必须存储不同的boost :: function对象的列表。 To provide this I'm using boost::any. 为此,我使用boost :: any。 I have a few functions which takes different functions signatures, pack them into any and then insert into special map with given type. 我有一些带有不同功能签名的功能,将它们打包到任何一个中 ,然后插入给定类型的特殊映射中。 Here is the code: 这是代码:
enum TypeEnumerator
{
e_int,
e_float,
e_double
};
typedef map< string, pair<any, TypeEnumerator> > CallbackType;
CallbackType mCallbacks;
void Foo(const string &name, function<float ()> f)
{
mCallbacks[name] = make_pair(any(f), CLASS::e_float);
}
void Foo(const string &name, function<int ()> f) { /* the same, but with e_int */ }
void Foo(const string &name, function<double ()> f) { /* the same, but with e_double */ }
Now I have in map boost function, packed into any with given type from enum, to recognize it in future. 现在,我有了map boost功能,可以将其封装到enum中具有给定类型的任何功能中,以便将来识别它。 Now I have to call given functions. 现在,我必须调用给定的函数。 The casting from any won't work: 任何类型的转换都不起作用:
BOOST_FOREACH(CallbackType::value_type &row, mCallbacks)
{
// pair<any, TypeEnumerator>
switch (row.second.second) // Swith the TypeEnumerator
{
case 0: // int
any_cast< function<int ()> >(row.first)();
break;
case 1: // float
any_cast< function<float ()> >(row.first)();
break;
case 2: // double
any_cast< function<double ()> >(row.first)();
break;
}
}
This won't cast and during running I get the exception: 这不会强制转换,在运行期间会出现异常:
what(): boost::bad_any_cast: failed conversion using boost::any_cast
Is it possible to convert back the boost::function object? 是否可以转换回boost :: function对象?
@TC provided the solution for the runtime error. @TC提供了运行时错误的解决方案。 But I believe you should use Boost.Variant instead of Boost.Any as there are only a fixed selection of types it can store. 但是我相信您应该使用Boost.Variant而不是Boost.Any,因为它只能存储固定的类型选择。 With Boost.Variant you could eliminate that enum too, as it already provided a standard visitor pattern interface. 使用Boost.Variant,您也可以消除该枚举,因为它已经提供了标准的访问者模式界面。 ( result ): ( 结果 ):
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/foreach.hpp>
#include <map>
#include <string>
#include <iostream>
typedef boost::variant<boost::function<int()>,
boost::function<float()>,
boost::function<double()> > Callback;
typedef std::map<std::string, Callback> CallbackType;
CallbackType mCallbacks;
void Foo(const std::string& name, const Callback& f) {
mCallbacks[name] = f;
}
//------------------------------------------------------------------------------
float f() {
std::cout << "f called" << std::endl;
return 4;
}
int g() {
std::cout << "g called" << std::endl;
return 5;
}
double h() {
std::cout << "h called" << std::endl;
return 4;
}
//------------------------------------------------------------------------------
struct call_visitor : public boost::static_visitor<> {
template <typename T>
void operator() (const T& operand) const {
operand();
}
};
int main () {
Foo("f", boost::function<float()>( f ));
Foo("g", boost::function<int()>( g ));
Foo("h", boost::function<double()>( h ));
BOOST_FOREACH(CallbackType::value_type &row, mCallbacks) {
boost::apply_visitor(call_visitor(), row.second);
}
return 0;
}
From the looks of it, row.first
is the name of the callback, a string
. 从外观row.first
, row.first
是回调的名称,即string
。 You should probably use row.second.first
: 您可能应该使用row.second.first
:
case 0: // int
any_cast< function<int ()> >(row.second.first)();
break;
Furthermore, you should use your enum constants in the switch ( case CLASS::e_int:
), instead of magic numbers. 此外,应该在开关( case CLASS::e_int:
使用枚举常量,而不是幻数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.