我试图创建一个通用的方法来包装C ++函数(另一种语言)。 我有(和和迭代器)的参数的列表和特定的C ++函数被调用的参数列表上。 我试图找到某种方式来解压的参数列表作为参数传递给我的功能。
我目前的做法是:
- 使用boost :: FunctionTypes获得功能序列的参数。
- 创建将包含的参数值,使用参数类型的值用于铸造一个boost ::融合名单。
- 调用与使用boost ::融合的调用所创建的列表的功能。
这两个步骤(1)和(2)似乎相当简单的事情。 但是,我想不出如何做第二步(或者如果它甚至有可能 - 混合编译时和运行时似乎有点怪)。
有没有人对如何做任何第二步,或者对这个问题的一个更好的办法的任何想法?
我知道的boost :: Python有做类似的事情,但代码是有点晦涩难懂,要了解眼前发生的良好意识。
更新
我有一个局部的解决方案,它适用于(至少)简单的案例。 目前仍然有处理引用问题。
希望有人可以张贴一些更好的解决方案。
该列表包含指向基类A,从其中所使用的所有其它类的。 我有两个子类B和C包含不同值类型(int和字符串)。
操作员转换需要给定类和获取潜在价值。 这些值被收集通过转化成其然后提供给调用的序列。
class A {
public:
A() {}
virtual ~A() {}
};
class B: public A {
protected:
int value;
public:
B() {}
B(int v): value(v) {}
int getValue() { return value; }
};
class C: public A {
protected:
string value;
public:
C() {}
C(const string &v): value(v) {}
string &getValue() { return value; }
};
// this pattern was copied from the test files from the fusion library
struct convert {
// keep a reference to the parameter we're going to unpack
list<A *>::iterator ¶m;
convert(list<A *>::iterator ¶m): param(param) {}
template<typename Sig>
struct result;
template <typename T>
struct result<convert(T)> {
typedef T type;
};
// this must be specialized in order to properly deal with the return types
template <typename T>
T operator ()(T type) const {}
};
template <>
int convert::operator ()(int type) const {
B *b = dynamic_cast<B *>(*param++);
if (b != NULL) return b->getValue();
throw error("illegal cast");
}
template <>
string convert::operator ()(string type) const {
C *c = dynamic_cast<C *>(*param++);
if (c != NULL) return c->getValue();
throw error("illegal cast");
}
最后,调用一个函数:
// create a parameter list (usually this would be passed to us)
list<A *> params;
params.push_back(new B(2));
params.push_back(new C("test"));
// point to beginning of parameter
list<A *>::iterator pos = params.begin();
// foo is the function we're going to call,
typedef BOOST_TYPEOF(foo) params_type;
// use the parameter list of foo to unpack the parameter list
auto passedParams = fusion::as_list(fusion::transform(function_types::parameter_types<params_type>(), trans(pos)));
// finally, call foo with the sequence that was created by the transform
fusion::invoke(foo, passedParams);