I have this sample code, which do what I need for a 3-parameter function :
template<typename T>T GETPARAM(void) { return T(); }
template<>int GETPARAM(void) { return 123; }
template<>double GETPARAM(void) { return 1.2345; }
template<>const char *GETPARAM(void) { return "hello"; }
template<typename P1, typename P2, typename P3, typename RES> RES BuildArgs3(RES(*fn)(P1, P2, P3)) {
P1 p1 = GETPARAM<P1>();
P2 p2 = GETPARAM<P2>();
P3 p3 = GETPARAM<P3>();
return fn(p1, p2, p3);
}
int print3(int a, double b, const char *c)
{
Cout() << "Print3:" << a << ", " << b << ", " << c << "\n";
return 1;
}
main() {
BuildArgs3(print3);
}
(the GETPARAM
templates are there just to show the call).
I tried to generalize it with a variadic template for functions with any number of arguments with no success. Is it possible ?
The template shall be useable for any T (*fn)(P1, P2, ...)
with any return type and any number of parameters, building the parameters on the fly calling the GETPARAM<Pn>()
for each of them.
It's needed to create a binding system for a scripting language, fetching parameters from a stack and calling a C++ function when done.
If the calls to
GETPARAM
should be ordered then you have to expand the variadic pack in a context that guarantees a particular order. One option is list initialization:Let us consider your given example: You can expand the argument pack yielding the
GETPARAM
calls inside the curly braces constructing a proxy object. The proxy object can be implicitly convertible to the return type of your function.Note that the upper version is the only one which guarantees ordered evaluation. In fact, I observe (online demo) the following output:
Here is a code for statically building any function with any number of arguments. It Is completely independent from any compiler as gcc and libraries as std or stl (excepting the
printf
's used, but you can remove them safely). But requires c++0x because of the variadic templates.Running it you will see the tests results:
You can run it with
clang++
to see the generated template code:References
Yes; and it's simple
The following is a full working example