vendredi 6 mars 2015

Automatic argument type deduction with variadic templates

I am currently writing a C++ <-> python wrapper using boost::python. In c++, i am using Eigen for numerical computation, while i use numpy in python. To be able to easily make wrappers for my c++ code i want to apply a transformation to each argument (for example casting from a python type to a c++ type), and then call the corresponding function.


Suppose the c++ method and the transformations are all Structs with the static method ´call´, i.e., simplified



struct cppFunction {
static double call(double a) { return a * 10; }
};

struct T1 {
static double call(int a) { return static_cast<double>(a); }
};


i then want to be able to do define a function that i can pass to Boost::Python



auto wrappedFunction = &wrap<CppFunction, T1>>


To do this, i need to automatically deduce the input arguments of CppFunction, i can do this with traits:



template <class F> struct ArgType;

template <class R, class T>
struct ArgType<R (*)(T)> {
typedef T argument_type;
};


with only 1 argument this can be implemented as:



template <typename Function, typename T1>
auto wrap(typename ArgType<decltype(&T1::call)>::argument_type a1)
-> decltype(Function::call(T1::call(a1))) {
return Function::call(T1::call(a1));
}
};


However, in the general case with a variadic number of inputs, it's natural to write:



struct cppFunction {
static double call(double a, double b, double c) { return a * b * c; }
};

template <typename Function, typename... T>
auto wrap(typename ArgType<decltype(&T::call)>::argument_type... a1)
-> decltype(Function::call(T::call(args)...)) {
return Function::call(T::call(args)...);
}

auto wrappedFunction = &wrap<CppFunction, T1, T1, T1>>


This however fails on my compiler (VS2013), complaining that ArgType::argument_type does not contain a parameter pack.


Is there any canonical way to implement what I am trying to do here?


Aucun commentaire:

Enregistrer un commentaire