我正在尝试自动化函数的生成,以便在基于变量的回调函数之间执行参数和结果封送。最终目标是简化回调到一种或多种脚本语言(可能是JavaScript和/或Lua)的集成。
我是c++模板元编程(和SO)的新手,所以我确信我在我的方法中犯了一堆新手错误。这是我到目前为止所做的…
namespace mpl = boost::mpl;
namespace ft = boost::function_types;
namespace fusion = boost::fusion;
typedef boost::variant<boost::none_t, bool, int, double, std::wstring> Variant;
typedef std::vector<Variant> VariantList;
template < typename T >
VariantList AppendVariantToList(VariantList list, const T &t)
{
list.push_back(t);
return list;
}
template < typename T >
T get(Variant &v)
{
return boost::get<T>(v);
}
typedef Variant callback_type(const VariantList &);
Variant InvokeCallback(const VariantList &args)
{
// This method will eventually invoke the actual script callback.
return true;
}
template < typename Function
, class From = typename mpl::begin<ft::parameter_types<Function>>::type
, class To = typename mpl::end<ft::parameter_types<Function>>::type
>
struct callback_binder
{
typedef typename mpl::deref<From>::type arg_type;
typedef typename mpl::next<From>::type next_iter_type;
template < int n >
static auto apply() -> decltype(boost::bind(AppendVariantToList<arg_type>, callback_binder<Function, next_iter_type, To>::apply<n + 1>(), boost::arg<n>()))
{
return boost::bind(AppendVariantToList<arg_type>, callback_binder<Function, next_iter_type, To>::apply<n + 1>(), boost::arg<n>());
}
static boost::function<Function> apply_1st(callback_type callback)
{
return boost::bind(get<bool>, boost::bind(callback, callback_binder<Function, From, To>::apply<1>()));
}
};
template < typename Function, class To >
struct callback_binder < Function, To, To >
{
template < int n >
static auto apply() -> decltype(boost::bind(boost::value_factory<VariantList>()))
{
return boost::bind(boost::value_factory<VariantList>());
}
};
template < typename Function >
boost::function<Function> make_callback(callback_type callback)
{
return callback_binder<Function>::apply_1st(callback);
}
bool OnSomeEvent(int a, int b)
{
const static auto callback(make_callback<BOOST_TYPEOF(OnSomeEvent)>(InvokeCallback));
return callback(a, b);
}
InvokeCallback
表示最终将调用脚本语言的函数的函数。OnSomeEvent
是我想要调用脚本回调函数的地方的一个示例。这个想法是,callback_binder::apply
方法迭代OnSomeEvent
的参数类型,并创建一个函子来填充VariantList
,调用InvokeCallback
并返回结果。
事情似乎进展顺利,直到我将< int n >
模板参数引入apply
方法,使我能够迭代boost::args
。不幸的是,试图编译上面的代码崩溃了vc++ 2010 RTM,所以我被困在如何继续。
编辑:也许我要问的具体问题是,"我如何在上面使用的'元循环'中访问boost::bind
的占位符?"
谢谢
西蒙。
我想我很像你:我总是想把这类任务自动化。
你可以使用模板来自动编组。
但是我更喜欢使用像SWIG这样的东西,简化包装器和接口生成器。http://www.swig.org/
不幸的是,上次我使用SWIG时,它不支持我正在使用的c++的所有标准语言特性。但这通常已经足够好了。
我也用过openc++。
我也使用gccxml, http://www.gccxml.org,虽然它是相当过时的。
参见属性&c++的反射库?
我没有使用XRTTI。
最后,我有时强迫自己使用一种宏语言,我可以很容易地预处理自己,以生成必要的代码。