1

我正在尝试创建一种通用的方法来包装 C++ 函数(来自不同的语言)。我有一个参数列表(和一个迭代器)和一个要在参数列表上调用的特定 C++ 函数。我试图找到某种方式将参数列表解压缩为我的函数的参数。

我目前的做法是:

  1. 使用 Boost::FunctionTypes 以序列的形式获取函数的参数。
  2. 使用参数类型的值进行转换,创建一个包含参数值的 Boost::Fusion 列表。
  3. 使用 boost::fusion 的调用使用创建的列表调用函数。

步骤 (1) 和 (2) 看起来都相当简单。但是,我不知道如何进行第二步(或者如果它甚至可能——混合编译时和运行时似乎有点奇怪)。

有没有人知道如何做第二步,或者解决这个问题的更好方法?

我知道 Boost::Python 必须做类似的事情,但是代码有点密集,以便很好地了解正在发生的事情。

更新

我有一个部分解决方案,它适用于(至少)简单的情况。处理参考仍然存在问题。

希望有人可以发布更好的解决方案。

该列表包含指向基类 A 的指针,所有其他使用的类都从该基类派生。我有两个子类 B 和 C,它们包含不同的值类型(int 和 string)。

运算符 convert 接受给定的类并获取基础值。这些值通过转换收集到一个序列中,然后将其提供给调用。

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 &param;

    convert(list<A *>::iterator &param): 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);
4

0 回答 0