1

I'm trying to create a generic way to wrap C++ functions (from a different language). I have a list of parameters (and and an iterator) and a specific C++ function to be called on the list of parameters. I'm trying to find someway to unpack the list of parameters as arguments to my function.

My current approach is to:

  1. Use Boost::FunctionTypes to get the parameters of the function as a sequence.
  2. Create a Boost::Fusion list that would contain the values of the arguments, using the values of the parameter types for casting.
  3. Call the function with the created list using boost::fusion's invoke.

Both the steps (1) and (2) seem fairly straightforward to do. However, I can't figure out how to do the second step (or if it's even possible -- mixing compile-time and run-time seems a little strange).

Does anyone have any idea of how to either do the second step, or a better approach on this problem?

I know Boost::Python has to do something similar, but the code is a little dense to get a good sense of what is happening.

update

I have a partial solution, which works for (at least) simple cases. There's still problems with dealing with reference.

Hopefully someone can post something better solution.

The list contains pointers to a base class A, from which all other classes used are derived. I have two subclasses B and C which contain different value types (int and string).

The operator convert takes the given class and gets the underlying value. These values are collected by transform into a sequence which is then given to invoke.

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");
}

and finally, to call a function:

// 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);
double-beep
  • 5,031
  • 17
  • 33
  • 41
Abe Schneider
  • 977
  • 1
  • 11
  • 23
  • You might find something useful within [my previous question](http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void). – chris Jun 22 '12 at 22:25
  • @chris: Thanks! One difference is that I'm working with a list of pointers to an object. However, it looks this might still work if I create a tuple from the list. If so, I think it might be a more elegant solution. – Abe Schneider Jun 23 '12 at 03:28
  • Stroustrup wrote an article back in 2000 describing prefix/suffix wrappers for a function. Do take a look at it. http://www.research.att.com/~bs/wrapper.pdf – Specksynder Jun 23 '12 at 03:46
  • @Specksyner: Thanks for the reference. However, this is a different type of wrapping I'm trying to do -- I want to call a function with parameters that are given in a list. In languages like Python I could just do: fn(*args) to unpack args as parameters to fn. I'm trying to find an equivalent for C++. – Abe Schneider Jun 23 '12 at 14:24

0 Answers0