Call sequence of template function for sequence of template parameters - c++

Let's imagine I have several template functions, e.g.:
template <int I> void f();
template <int I> void g();
template <int I> void h();
How can I call sequence of any of these functions for sequence of template parameters?
In other words, I need such behaviour:
{some template magic}<1, 5>(f); // This is pseudocode, I don't need exactly this format of calling.
unrolls into:
f<1>();
f<2>();
f<3>();
f<4>();
f<5>();
And I need the same method to work for every of my functions (not only for f, but for g and h too) without writing big awkward structure for every of these functions.
I can use C++11, and even already implemented in latest development gcc version C++1y/C++14 functionality (http://gcc.gnu.org/projects/cxx1y.html), e.g. polymorphic lambdas.

With C++1y features. Instead of calling the function directly and passing the template argument as, well, a template argument, you can create a lambda that takes a function argument which contains the template argument as part of its type. I.e.
f<42>();
[](std::integral_constant<int, 42> x) { f<x.value>(); }
[](auto x) { f<x.value>(); }
With this idea, we can pass the function template f around, when wrapped into such a polymorphic lambda. That's possible for any kind of overload set, one of the things you can't do with ordinary lambdas.
To call f with a sequence of template arguments, we'll need the common indices classes for the indices expansion trick. Those will be in the C++1y Standard Library. Coliru's clang++ compiler for example still uses an older libstdc++ which doesn't have them AFAIK. But we can write our own:
#include <utility>
using std::integral_constant;
using std::integer_sequence; // C++1y StdLib
using std::make_integer_sequence; // C++1y StdLib
// C++11 implementation of those two C++1y StdLib classes:
/*
template<class T, int...> struct integer_sequence {};
template<class T, int N, int... Is>
struct make_integer_sequence : make_integer_sequence<T, N-1, N-1, Is...> {};
template<class T, int... Is>
struct make_integer_sequence<T, 0, Is...> : integer_sequence<T, Is...> {};
*/
When we write make_integer_sequence<int, 5>, we'll get a type that's derived from integer_sequence<int, 0, 1, 2, 3, 4>. From the latter type, we can deduce the indices:
template<int... Indices> void example(integer_sequence<int, Indices...>);
Inside this function, we have access to the indices as a parameter pack. We'll use the indices to call the lamba / function object f as follows (not the function template f from the question):
f( integral_constant<int, Indices>{} )...
// i.e.
f( integral_constant<int, 0>{} ),
f( integral_constant<int, 1>{} ),
f( integral_constant<int, 2>{} ),
// and so on
Parameter packs can only be expanded in certain contexts. Typically, you'd expand the pack as initializers (e.g. of a dummy array), as the evaluation of those is are guaranteed to be ordered (thanks, Johannes Schaub). Instead of an array, one could use a class type such as
struct expand { constexpr expand(...) {} };
// usage:
expand { pattern... };
A dummy array looks like this:
int expand[] = { pattern... };
(void)expand; // silence compiler warning: `expand` not used
Another tricky part is to deal with functions returning void as the pattern. If we combine a function call with a comma operator, we always get a result
(f(argument), 0) // always has type int and value 0
To break any existing overloaded comma operators, add a void()
(f(argument), void(), 0)
Finally, combine all the above to create magic:
template<int beg, class F, int... Is>
constexpr void magic(F f, integer_sequence<int, Is...>)
{
int expand[] = { (f(integral_constant<int, beg+Is>{}), void(), 0)... };
(void)expand;
}
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~~~v see below (*)
return magic<beg>(f, make_integer_sequence<int, end-beg+1>{});
}
Usage example:
#include <iostream>
template<int N> void f() { std::cout << N << "\n"; }
int main()
{
//magic<1, 5>( [](auto x) { f<decltype(x)::value>(); } );
magic<1, 5>( [](auto x) { f<x.value>(); } );
}
(*) IMHO end-beg+1 is bad practice. There's a reason why the StdLib works with half-open ranges of the form [begin, end): The empty range simply is [begin, begin). With the StdLib using half-open ranges, it might be inconsistent to use closed ranges here. (There's one exception in the StdLib I know of, it has to do with PRNGs and the maximum integer value.)
I'd suggest you'd design your magic interface to take half-open ranges, i.e.
magic<1, 6>( [](auto x) { f<x.value>(); } ); // [1, 6) i.e. {1,2,3,4,5}
with the implementation
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~v
return magic<beg>(f, make_integer_sequence<int, end-beg>{});
}
Note the weird +1 disappears.

Using reified functions and template template arguments:
#include <iostream>
template<int I> class f {
public:
static void call() {
std::cout << I << '\n';
}
};
template<template<int I> class X, int I, int J> class magic {
public:
static void call() {
X<I>::call();
magic::call();
}
};
template<template<int I> class X, int I> class magic<X,I,I> {
public:
static void call() {
X<I>::call();
}
};
int main(int argc, char** argv) {
magic<f,2,6>::call();
return 0;
}

Related

Dynamic Dispatch to Template Function C++

I have a template function (in my case a cuda kernel), where there are a small number of boolean template parameters that can chosen between at runtime. I am happy to instantiate all permutations at compile time and dispatch dynamically, like so (for boolean b0,b1,b2):
if (b0) {
if (b1) {
if (b2) {
myFunc<true,true,true,otherArgs>(args);
} else {
myFunc<true,true,false,otherArgs>(args);
}
} else {
if(b2) {
myFunc<true,false,true,otherArgs>(args);
} else {
myFunc<true,false,false,otherArgs>(args);
}
}
} else {
if(b1) {
if(b2) {
myFunc<false,true,true,otherArgs>(args);
} else {
myFunc<false,true,false,otherArgs>(args);
}
} else {
if(b2) {
myFunc<false,false,true,otherArgs>(args);
} else {
myFunc<false,false,false,otherArgs>(args);
}
}
}
This is annoying to write, and gets exponentially worse if I end up with a b3 and b4.
Is there a simple way to rewrite this in a more concise way in C++11/14 without bringing in large external libraries (like boost)? Something like:
const auto dispatcher = construct_dispatcher<bool, 3>(myFunc);
...
dispatcher(b0,b1,b2,otherArgs,args);
No problem.
template<bool b>
using kbool = std::integral_constant<bool, b>;
template<std::size_t max>
struct dispatch_bools {
template<std::size_t N, class F, class...Bools>
void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
{
if (input[max-1])
dispatch_bools<max-1>{}( input, continuation, kbool<true>{}, Bools{}... );
else
dispatch_bools<max-1>{}( input, continuation, kbool<false>{}, Bools{}... );
}
};
template<>
struct dispatch_bools<0> {
template<std::size_t N, class F, class...Bools>
void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
{
continuation( Bools{}... );
}
};
Live example.
So kbool is a variable with represents a compile time constant boolean. dispatch_bools is a helper struct that has an operator().
This operator() takes an array of runtime bools, and starting at max-1 proceeds to spawn max if/else branches, each recursing into call to dispatch_bools with one more compile-time bool calculated.
This generates 2^max code; exactly the code you don't want to write.
The continuation is passed all the way down to the bottom recursion (where max=0). At that point, all of the compile-time bools have been built up -- we call continuation::operator() passing in those compile-time bools as function parameters.
Hopefully continuation::operator() is a template function that can accept compile-time bools. If it is, there are 2^max instantiations of it, each with each of the 2^max possible true/false combinations.
To use this to solve your problem in c++14 you just do:
std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, [&](auto...Bargs){
myFunc<decltype(Bargs)::value...,otherArgs>(args);
});
This is easy because c++14 has auto lambdas; it can have a template operator() on a lambda. Turning those compile-time bool arguments back into template non-type arguments is easy.
Note that many nominally c++11 compilers support auto-lambdas, because of how easy it was. However, if you lack it, you can still solve this in c++11 with a helper struct:
template<class OtherArgs>
struct callMyFunc {
Args args;
template<class...Bools>
void operator()(Bools...){
myFunc<Bools::value...,otherArgs>(args);
}
};
now use is:
std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, callMyFunc<otherArgs>{args});
This is basically manually writing what the c++14 lambda would do.
In c++14 you can replace void with auto and return instead of just recursing and it will deduce a return type for you reasonably well.
If you want that feature in c++11 you can either write a lot of decltype code, or you can use this macro:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
and write the body of dispatch_bools like:
template<class T, std::size_t N, class F, class...Bools>
auto operator()( std::array<T, N> const& input, F&& continuation, Bools... )
RETURNS(
(input[max-1])?
dispatch_bools<max-1>{}( input, continutation, kbool<true>{}, Bools{}... )
:
dispatch_bools<max-1>{}( input, continutation, kbool<false>{}, Bools{}... )
)
and similar for the <0> specialization, and get c++14 style return deduction in c++11.
RETURNS makes deducing return types of one-liner functions trivial.
Is there a simple way? No. Can it be done using an unholy mess of garbled templates? Sure, why not.
Implementation
First, this is going to be a bit easier if we have a class rather than a function, simply because parameterized classes can be passed as template parameters. So I'm going to write a trivial wrapper around your myFunc.
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
This is just a class for which MyFuncWrapper<...>()(extra) is equivalent to myFunc<...>(extra).
Now let's make our dispatcher.
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
Whew, there's quite a bit to explain there. The Dispatcher class has two template arguments and then a variadic list. The first two arguments are simple: the function we want to call (as a class) and the "extra" argument type. The variadic argument will start out empty, and we'll use it as an accumulator during the recursion (similar to an accumulator when you're doing tail call optimization) to accumulate the template Boolean list.
dispatch is just a recursive template function. The base case is when we don't have any arguments left, so we just call the function with the arguments we've accumulated so far. The recursive case involves a conditional, where we accumulate a true if the Boolean is true and a false if it's false.
We can call this with
Dispatcher<MyFuncWrapper, TypeOfExtraArgument>()
.dispatch(extraArgument, true, true, false);
However, this is a bit verbose, so we can write a macro to make it a bit more approachable.1
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
Now our call is
DISPATCH(MyFuncWrapper, extraArgument, true, true, false);
Complete Runnable Example
Includes a sample myFunc implementation.
#include <utility>
#include <iostream>
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
template <bool a, bool b, bool c, typename T>
void myFunc(T&& extra) {
std::cout << a << " " << b << " " << c << " " << extra << std::endl;
}
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
int main() {
DISPATCH(MyFuncWrapper, 17, true, true, false);
DISPATCH(MyFuncWrapper, 22, true, false, true);
DISPATCH(MyFuncWrapper, -9, false, false, false);
}
Closing Notes
The implementation provided above will let myFunc return values as well, although your example only included a return type of void, so I'm not sure you'll need this. As written, the implementation requires C++14 for auto return types. If you want to do this under C++11, you can either change all the return types to void (can't return anything from myFunc anymore) or you can try to hack together the return types with decltype. If you want to do this in C++98, ... ... ... ... good luck
1 This macro is susceptible to the comma problem and thus won't work if you pass it zero Booleans. But if you're not going to pass any Booleans, you probably shouldn't be going through this process anyway.

Passing references to a variadic-templates use the std::reference-wrapper

I try to pass to a variadic template function a list of references and pass it to another function. The code that I wrote is the following:
template <typename T>
void fun(cv::Point_<T> & pt) { pt.x++; pt.y++; }
template <class ... args>
void caller(args & ... list) {
typedef typename std::tuple_element<0, std::tuple<args...> >::type T;
std::array<std::reference_wrapper<T>, sizeof...(list)> values {list ... };
for(int i=0; i<values.size(); i++)
fun(values[i]);
}
then I call the function caller in this way:
cv::Point2f a, b, c;
caller(a, b, c);
the compiler give me the following error:
No matching function for call to 'fun'
Candidate template ignored: could not match 'Point_' against 'reference_wrapper'
what I missing?
Although std::reference_wrapper<T> has an implicit conversion to T&, you cannot use both an implicit conversion and template argument deduction at the same time, and template argument deduction is necessary to call fun.
Try
fun(values[i].get());
Even simpler is
template <typename...Args>
void caller(Args&...args)
{
auto tmp = { (func(args),0)..., 0 };
}
This uses the fact that parameter pack expansion can occur in braced init lists. Since func() returns void, we cannot simply use { func(args)... }, but use (func(args),0) to have an int. Finally, the last 0 is to ensure that the code compiles (and does nothing) in case of an empty parameter pack.
You can generalise this and write a template that calls a given generic function for every element of a pack:
template <typename Func, typename...Args>
void call_for_each(Func &&func, Args&&...args)
{
auto unused = { (func(std::forward<Args>(args)),0)...,0 };
}
which may be used like this (C++14)
int main()
{
int a=1;
double b=2.4;
auto func = [](auto&x) { std::cout<<' '<<x++; };
call_for_each(func,a,b);
std::cout<<'\n';
call_for_each(func,a,b);
std::cout<<'\n';
}
This uses a C++14 lambda (taking an auto argument). Note that the parameter pack must come last among the template parameters of call_for_each.
Since the goal of this might be to iterate over all args, here's a more generic solution. We are going to implement for_pack:
template<typename... Args, typename F>
void for_pack(F function, Args&&... args) {
using expand = int[];
(void)expand{(function(std::forward<Args>(args)), void(), 0)..., 0};
}
This will execute function for every args in Args.
Now, your function caller is much more trivial to implement:
template <typename... args>
void caller(args&... list) {
for_pack([&](cv::Point_<T>& arg){
fun(arg);
}, list...);
}
Since a google search for "c++ pass reference parameters to variadic template" gives this as first result, I'll put this generic solution here.
struct HH { /*...*/ void change_me() { /*...*/ } };
template<typename...T> void parms_r_refs() {}
template<typename H, typename...T> void parms_r_refs(H &h, T&...t) { h.change_me(); parms_r_refs(t...); }
template<typename...T> void parms_r_refs(T&...t) { parms_r_refs(t...); }
HH a, b, c;
..
parms_r_refs(a, b, c);
..

C++ variadic template arguments method to pass to a method without variadic arguments

I have the following question, I really can't compile from all the questions and articles researched:
In C++, is it possible to have a method with variadic template arguments that specify types of arguments (as a meta-description type for parameters of in, out, in/out of a certain type, to be passed by value, by address etc.), to loop through these variadic arguments in order to instantiate variables of specified types, and be passed these variables to functions specified by a pointer in a template parameter, but these functions not having variadic parameters?
EDIT 1
I try here to detail, as pseudocode:
template <decltype(*Type::*Method), typename... Parameters>
static bool ExecuteMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
loop through Parameters
{
Parameters[i]::Type p[i] <-- args[i];
}
ReturnType r = Method(p[0], p[1], p[2] .. p[n]); // the method does not have variadic parameters
...
}
where Method might be like:
int(*GetColor) ( int16 *color);
int(*GetFile) ( FilePath &file );
int(*WriteDocument) ( const FilePath &file, const char *fileFormatName, bool askForParms);
etc.
This comes out of wrapping needs.
The challenge is something missing in C++, reflection as in .net.
It is possible to instance an array of heterogeneous objects by looping through the variadic arguments somehow? Probably.
But how pass them to methods having no variadic arguments? I think it is not possible to assign that array of objects to functions like these three above without explicit wrappers, isn't it?
EDIT 2
I've got a lot of feed-back, but it is clear I was not specific enough.
I did not detailed too much because I've got complains in the past for being too specific. Indeed, I do not have easy implementations and I am a generic guy, not lazy, but I try to make a latter development faster.
Here is the source of the problem: I need to wrap Adobe Illustrator API, which exposes hundreds if not thousands of pointers to functions grouped in structs, called suites.
I try to have a javascript engine using SpiderMonkey.
I use Visual Studio 2015 compiler.
My approach is as follows:
I have several classes to wrap the API in order to add to SpiderMonkey's engine objects for all the suites. Each SpiderMonkey class, could be called as jsData, wraps a data type of Adobe SDK, or a suite, jsSuite.
So far, I have used templates because SpiderMonkey forces me to add each function to its custom objects with a specific signature, like this:
bool jsAIDocumentSuite::WriteDocument(JSContext *cx, unsigned argc, JS::Value *vp)
{
...
}
and adding it to the custom object would be done like this:
const JSFunctionSpec jsAIDocumentSuite::fFunctions[] = {
...
JS_FN("WriteDocument", jsAIDocumentSuite::WriteDocument, 3, 0),
...
}
JS_FN is a SpiderMonkeyMacro.
Actually, this is, so far, less than 10% of the Adobe SDK.
The most are getters and setters with one parameter, passed by value or address or pointer, so I have replaced them by a generic function, like this:
template <typename jsType, typename jsReturnType, typename ReturnPrivateType = jsReturnType::PrivateType, typename jsParamType, typename ParamPrivateType = jsParamType::PrivateType, ReturnPrivateType(*Type::*Method)(ParamPrivateType&)>
static bool GetByRefMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
try
{
ReturnPrivateType result;
ParamPrivateType ppt;
if (jsType::Suite() && (jsType::Suite()->*Method))
result = (jsType::Suite()->*Method)(ppt);
else
return false; // TODO throw a meaningful error
if ((jsReturnType::IsNoError(result)) && (argc > 0) && (args[0].isObject()))
{
JSObject *obj = &args[0].toObject();
JSObject *value = NULL;
if (!jsParamType::FromAIObject<jsParamType>(cx, &ppt, value))
return false;
if (!value)
return false;
jsProperty::SetProperty(cx, &obj, "value", value, true);
}
JSObject *obj = JS_NewObject(cx, &jsDataClass<jsReturnType>::fClass);
JS_SetPrivate(obj, new ReturnPrivateType(result));
args.rval().setObject(*obj);
}
EXCEPTION_CATCH_CONVERT();
return true;
}
A bit complicated, isn't it?
What is relevant, above, is:
The args variable holds the SpiderMonkey parameters passed in by its engine
Only one argument is passed here, ppt
The return type is one value, so it is easy to be handled
I use macros to inject the method in its variants (several short forms too, not so interesting here):
JS_FN(#GET_METHOD, (js##TYPE::GetByRefMethod<js##TYPE, RETURN_JS_TYPE, RETURN_PRIVATE_TYPE, PARAM_JS_TYPE, PARAM_PRIVATE_TYPE, &TYPE::GET_METHOD>), 1, 0)
I wish to be able to handle variable arguments, according to the statistics more philosophical, but interesting. The idea would be opposite to the C++, probably, and not as expected.
How would I expect it:
I wish to add variadic parameters meta-information, like:
template
static bool Method(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
try
{
ReturnPrivateType result;
*1st challenge: Loop through the variadic list of meta-parameters and create their corresponding object instances here and initialize the IN ones with values from the *args* collection passed by the SpiderMonkey engine*
if (jsType::Suite() && (jsType::Suite()->*Method))
result = (jsType::Suite()->*Method)(*2nd challenge: pass arguments here: probably by using a variadic macro?*);
else
return false; // TODO throw a meaningful error
if ((jsReturnType::IsNoError(result)) && (argc > 0) && (args[0].isObject()))
{
JSObject *obj = &args[0].toObject();
JSObject *value = NULL;
if (!jsParamType::FromAIObject<jsParamType>(cx, &ppt, value))
return false;
if (!value)
return false;
jsProperty::SetProperty(cx, &obj, "value", value, true);
}
JSObject *obj = JS_NewObject(cx, &jsDataClass<jsReturnType>::fClass);
JS_SetPrivate(obj, new ReturnPrivateType(result));
args.rval().setObject(*obj);
}
EXCEPTION_CATCH_CONVERT();
return true;
}
As you can see, it is not as C++ expected, it is a bit reversed, by trying to avoid writing templates to deduct the parameters, here, I know the parameters first and try to write a code to generate the right parameters by knowing their meta-information first and I have a clear set of types and I promise to write the right code to generate the correct wrappers. I don't need to validate much regarding the data of the parameters, as things are mostly passed without a huge business logic in the process.
EDIT 3
About the parameters meta-information, I could write a few types with statics to specify the data type of the parameter, whether it is a return type, whether it is an IN, an OUT or an IN/OUT parameter, its jsType etc..
They would be the variadic list of the template parameters function above.
I still am having some difficulty understanding exactly what you want to do, but this should let you call a function(without variardic parameters) using a variardic template function, getting the parameters from an array and allowing a conversion operation to apply to each parameter before being passed to the function:
#include <functional>
template<typename T, typename JST> T getParam(const JST& a)
{
//Do whatever conversion necessary
return a;
}
namespace detail
{
template<typename R, typename... Args, int... S> R jsCaller(std::function<R(Args...)> f, seq<S...>, const JS::CallArgs& args)
{
return f(getParam<Args, /*Whatever type should go here */>(args[S])...);
}
}
//Actually use this to call the function and get the result
template<typename R, typename... Args> R jsCall(std::function<R(Args...)> f, const JS::CallArgs& args)
{
return detail::jsCaller(f, GenSequence<sizeof...(Args)>(), args);
}
Where GenSequence extends seq<0, 1, 2, ... , N - 1> and can be implemented as follows:
template<int... N>
struct seq {};
template<int N, int... S>
struct gens : gens<N-1, N-1, S...> {};
template<int... S>
struct gens<0, S...>
{
typedef seq<S...> type;
};
template<int N> using GenSequence<N> = typename gens<N>::type;
This creates a parameter pack of integers, and expands the function call using them- See this question.
You can call your method using jsCall:
Result r = jsCall((Method), args);
Assuming Method can be converted to std::function- if not, you can still do it by making a lambda which conforms to std::function. Does this solve the problem?
[Continued from part 1: https://stackoverflow.com/a/35109026/5386374 ]
There is an issue, however. We had to change the way our code is written to accomodate ExecuteMethod(), which may not always be possible. Is there a way around that, so that it functions exactly the same as your previously specified ExecuteMethod(), and doesn't need to take the variable it modifies as a macro parameter? The answer is... yes!
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Instead of a do...while structure, we can just use a temporary Executor directly.
// MSVC:
// #define ExecuteMethod(M, ...) Executor<decltype(&M), decltype(&M)>{}(M, __VA_ARGS__)
// GCC:
#define ExecuteMethod(M, ...) Executor<decltype(&M), decltype(&M)>{}(M, ##__VA_ARGS__)
// For your example function WriteDocument(), defined as
// int WriteDocument(const FilePath &file, const char *fileFormatName, bool askForParms);
bool c = ExecuteMethod(WriteDocument, file, fileFormatName, askForParams);
This is all well and good, but there is one more change we can make to simplify things without impacting performance. At the moment, this functor can only take function pointers (and maybe lambdas, I'm not familiar with their syntax), not other types of function objects. If this is intended, it means that we can rewrite it to do away with the first template parameter (the entire signature), since the second and third parameters are themselves components of the signature.
// Default functor.
template<typename... Ts>
struct Executor { };
// General case.
template<typename ReturnType, typename... Params>
struct Executor<ReturnType (*)(Params...)> {
private:
// Instead of explicitly taking M as a parameter, create it from
// the other parameters.
using M = ReturnType (*)(Params...);
public:
// Parameter match:
bool operator()(M method, Params... params) {
ReturnType r = method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Special case to catch void return type.
template<typename... Params>
struct Executor<void (*)(Params...)> {
private:
// Instead of explicitly taking M as a parameter, create it from
// the other parameters.
using M = void (*)(Params...);
public:
// Parameter match:
bool operator()(M method, Params... params) {
method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Instead of a do...while structure, we can just use a temporary Executor directly.
// MSVC:
// #define ExecuteMethod(M, ...) Executor<decltype(&M)>{}(M, __VA_ARGS__)
// GCC:
#define ExecuteMethod(M, ...) Executor<decltype(&M)>{}(M, ##__VA_ARGS__)
// Note: If your compiler doesn't support C++11 "using" type aliases, replace them
// with the following:
// typedef ReturnType (*M)(Params...);
This results in cleaner code, but, as mentioned, limits the functor to only accepting function pointers.
When used like this, the functor expects parameters to be an exact match. It can handle reference-ness and cv-ness correctly, but may have issues with rvalues, I'm not sure. See here.
As to how to use this with your JSContext... I'm honestly not sure. I haven't learned about contexts yet, so someone else would be more helpful for that. I would suggest checking if one of the other answers here would be more useful in your situation, in all honesty.
Note: I'm not sure how easy it would be to modify the functor to work if its function parameter is a functor, lambda, std::function, or anything of the sort.
Note 2: As before, I'm not sure if there would be any negative effects on performance for doing something like this. There's likely a more efficient way, but I don't know what it would be.
I came up with the following C++11 solution, which gives the basic idea. It could very easily be improved, however, so I welcome suggestions. Live test here.
#include <iostream>
#include <tuple>
using namespace std;
// bar : does something with an arbitrary tuple
// (no variadic template arguments)
template <class Tuple>
void bar(Tuple t)
{
// .... do something with the tuple ...
std::cout << std::tuple_size<Tuple>::value;
}
// foo : takes a function pointer and an arbitrary number of other
// arguments
template <class Func, typename... Ts>
void foo(Func f, Ts... args_in)
{
// construct a tuple containing the variadic arguments
std::tuple<Ts...> t = std::make_tuple(args_in...);
// pass this tuple to the function f
f(t);
}
int main()
{
// this is not highly refined; you must provide the types of the
// arguments (any suggestions?)
foo(bar<std::tuple<int, const char *, double>>, 123, "foobar", 43.262);
return 0;
}
Edit: After seeing your "Edit 2", I don't believe this is the proper solution. Leaving it up for reference, though.
I believe I've found a potential solution that catches reference-ness, too. Scroll down to the bottom, to the "Edit 4" section.
If you're asking whether it's possible to dynamically check template argument types, you can. I'll start with a general example of how to use std::true_type and std::false_type to overload based on whether a specified condition is met, then move on to your problem specifically. Consider this:
#include <type_traits>
namespace SameComparison {
// Credit for the contents of this namespace goes to dyp ( https://stackoverflow.com/a/20047561/5386374 )
template<class T, class...> struct are_same : std::true_type{};
template<class T, class U, class... TT> struct are_same<T, U, TT...> :
std::integral_constant<bool, std::is_same<T, U>{} && are_same<T, TT...>{} >{};
} // namespace SameComparison
template<typename T> class SomeClass {
public:
SomeClass() = default;
template<typename... Ts> SomeClass(T arg1, Ts... args);
~SomeClass() = default;
void func(T arg1);
template<typename U> void func(U arg1);
template<typename... Ts> void func(T arg1, Ts... args);
template<typename U, typename... Ts> void func(U arg1, Ts... args);
// ...
private:
template<typename... Ts> SomeClass(std::true_type x, T arg1, Ts... args);
template<typename... Ts> SomeClass(std::false_type x, T arg1, Ts... args);
// ...
};
// Constructors:
// -------------
// Public multi-argument constructor.
// Passes to one of two private constructors, depending on whether all types in paramater pack match T.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(T arg1, Ts... args) :
SomeClass(SameComparison::are_same<T, Ts...>{}, arg1, args...) { }
// All arguments match.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(std::true_type x, T arg1, Ts... args) { }
// One or more arguments is incorrect type.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(std::false_type x, T arg1, Ts... args) {
static_assert(x.value, "Arguments wrong type.");
}
/*
Note that if you don't need to use Ts... in the parameter list, you can combine the previous two into a single constructor:
template<typename T> template<bool N, typename... Ts> SomeClass<T>::SomeClass(std::integral_constant<bool, N> x, T arg1, Ts... args) {
static_assert(x.value, "Arguments wrong type.");
}
x will be true_type (value == true) on type match, or false_type (value == false) on type mismatch. Haven't thoroughly tested this, just ran a similar function through an online compiler to make sure it could determine N.
*/
// Member functions:
// -----------------
// Single argument, type match.
template<typename T> void SomeClass<T>::func(T arg1) {
// code
}
// Single argument, type mismatch.
// Also catches true_type from multi-argument functions after they empty their parameter pack, and silently ignores it.
template<typename T> template<typename U> void SomeClass<T>::func(U arg1) {
if (arg1 != std::true_type{}) {
std::cout << "Argument " << arg1 << " wrong type." << std::endl;
}
}
// Multiple arguments, argument 1 type match.
template<typename T> template<typename... Ts> void SomeClass<T>::func(T arg1, Ts... args) {
func(arg1);
func(args...);
// func(SameComparison::are_same<T, Ts...>{}, vals...);
}
// Multiple arguments, argument 1 type mismatch.
template<typename T> template<typename U, typename... Ts> void SomeClass<T>::func(U arg1, Ts... args) {
// if (arg1 != std::true_type{}) {
// std::cout << "Argument " << arg1 << " wrong type." << std::endl;
// }
func(vals...);
}
First, SameComparison::are_same there is an extension of std::is_same, that applies it to an entire parameter pack. This is the basis of the check, with the rest of the example showing how it can be used. The lines commented out of the last two functions show how it could be applied there, as well.
Now, onto your problem specifically. Since you know what the methods are, you can make similar comparison structs for them.
int (*GetColor) ( int16_t *color);
int(*GetFile) ( FilePath &file );
int(*WriteDocument) ( const FilePath &file, const char *fileFormatName, bool askForParms);
Could have...
namespace ParameterCheck {
template<typename T, typename... Ts> struct parameter_match : public std::false_type {};
// Declare (GetColor, int16_t*) valid.
template<> struct parameter_match<int (*)(int16_t*), int16_t*> : public std::true_type {};
// Declare (GetFile, FilePath&) valid.
// template<> struct parameter_match<int (*)(FilePath&), FilePath&> : public std::true_type {}; // You'd think this would work, but...
template<> struct parameter_match<int (*)(FilePath&), FilePath> : public std::true_type {}; // Nope!
// For some reason, reference-ness isn't part of the templated type. It acts as if it was "template<typename T> void func(T& arg)" instead.
// Declare (WriteDocument, const FilePath&, const char*, bool) valid.
// template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath, const char*, bool> : public std::true_type {};
// template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath&, const char*, bool> : public std::true_type {};
template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), FilePath, const char*, bool> : public std::true_type {};
// More reference-as-template-parameter wonkiness: Out of these three, only the last works.
} // namespace ParameterCheck
Here, we make a general-case struct that equates to std::false_type, then specialise it so that specific cases are true_type instead. What this does is tell the compiler, "These parameter lists are good, anything else is bad," where each list starts with a function pointer and ends with the arguments to the function. Then, you can do something like this for your caller:
// The actual calling function.
template<typename Func, typename... Ts> void caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> void caller2(std::false_type x, Func f, Ts... args) {
std::cout << "Parameter list mismatch." << std::endl;
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> void caller(Func f, Ts... args) {
caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
}
As for return type deduction... that depends on where you want to deduce it:
Determine variable type from contents: Use auto when declaring the variable.
Determine return type from passed function return type: If your compiler is C++14-compatible, that's easy. Just use auto. [VStudio 2015 and GCC 4.8.0 (with -std=c++1y) are compatible with auto return type.]
The former can be done like this:
int i = 42;
int func1() { return 23; }
char func2() { return 'c'; }
float func3() { return -0.0f; }
auto a0 = i; // a0 is int.
auto a1 = func1(); // a1 is int.
auto a2 = func2(); // a2 is char.
auto a3 = func3(); // a3 is float.
The latter, however, is more complex.
std::string stringMaker() {
return std::string("Here, have a string!");
}
int intMaker() {
return 5;
}
template<typename F> auto automised(F f) {
return f();
}
// ...
auto a = automised(stringMaker); // a is std::string.
auto b = automised(intMaker); // a is int.
If your compiler isn't compatible with auto or decltype(auto) return type... well, it's a bit more verbose, but we can do this:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
// ...
std::string f1() {
return std::string("Nyahaha.");
}
int f2() {
return -42;
}
char f3() {
return '&';
}
template<typename R, typename F> auto rtCaller2(R r, F f) -> typename R::type {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(ReturnTypeCapture::ret_type<F>{}, f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
// ...
rtCaller(f1); // Output (with gcc): "Nyahaha. (type: Ss)"
rtCaller(f2); // Output (with gcc): "-42 (type: i)"
rtCaller(f3); // Output (with gcc): "& (type: c)"
Furthermore, we can simplify it even more, and check the return type without a separate wrapper.
template<typename F> auto rtCaller2(F f) -> typename ReturnTypeCapture::ret_type<F>::type {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
// ...
rtCaller(f1); // Output (with gcc): "Nyahaha. (type: Ss)"
rtCaller(f2); // Output (with gcc): "-42 (type: i)"
rtCaller(f3); // Output (with gcc): "& (type: c)"
// Same output.
Having that sticking off the end there is really ugly, though, so can't we do better than that? The answer is... yes! We can use an alias declaration to make a typedef, leaving a cleaner name. And thus, the final result here is:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
template <typename F> using RChecker = typename ReturnTypeCapture::ret_type<F>::type;
std::string f1() { return std::string("Nyahaha."); }
int f2() { return -42; }
char f3() { return '&'; }
template<typename F> auto rtCaller2(F f) -> RChecker<F> {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
So now, if we combine parameter checking & return type deduction...
// Parameter match checking.
namespace ParameterCheck {
template<typename T, typename... Ts> struct parameter_match : public std::false_type {};
// Declare (GetColor, int16_t*) valid.
template<> struct parameter_match<int (*)(int16_t*), int16_t*> : public std::true_type {};
// Declare (GetFile, FilePath&) valid.
template<> struct parameter_match<int (*)(FilePath&), FilePath> : public std::true_type {};
// Declare (WriteDocument, const FilePath&, const char*, bool) valid.
template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), FilePath, const char*, bool> : public std::true_type {};
// Declare everything without a parameter list valid.
template<typename T> struct parameter_match<T (*)()> : public std::true_type { };
} // namespace ParameterCheck
// Discount return type deduction:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
// Alias declarations:
template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts...>;
template<typename F> using RChecker = typename ReturnTypeCapture::ret_type<F>::type;
// ---------------
int GetColor(int16_t* color);
int GetFile(FilePath& file);
int WriteDocument(const FilePath& file, const char* fileFormatName, bool askForParams);
std::string f1() { return std::string("Nyahaha."); }
int f2() { return -42; }
char f3() { return '&'; }
// ---------------
// Calling function (C++11):
// The actual calling function.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Parameter list mismatch." << std::endl;
return static_cast<RChecker<Func> >(0); // Just to make sure we don't break stuff.
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) -> RChecker<Func> {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
// ---------------
// Calling function (C++14):
// The actual calling function.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) {
std::cout << "Parameter list mismatch." << std::endl;
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
You should be able to get the functionality you want out of this, I believe. The only caveat is that if you do it this way, you need to explicitly declare functions valid in ParameterCheck, by making a template specialisation for the function & its parameter list, derived from std::true_type instead of std::false_type. I'm not sure if there's a way to get true dynamic parameter list checking, but it's a start.
[I'm not sure if you can just overload caller() or if you explicitly need to use caller2() as well. All my attempts to overload caller() via template parameters ended up crashing the compiler; for some reason, it chose template<typename Func, typename... Ts> void caller(Func f, Ts... args) as a better match for caller(std::true_type, f, args...) than template<typename Func, typename... Ts> caller(std::true_type x, Func f, Ts... args), even with the latter listed before the former, and tried to recursively expand it until it ran out of memory. (Tested on two online gcc compilers: Ideone, and TutorialsPoint's compiler (with -std=c++11). I'm not sure if this is a gcc problem, or if I was a bit off about how template matching works. Unfortunately, the online VStudio compiler is down for maintenance, and the only version of VS I have available to me offline at the moment doesn't support variadic templates, so I can't check which is the case.) Unless someone says otherwise, or says how to fix that particular issue, it's probably best to just use caller() as a wrapper & caller2() to do the heavy lifting.]
Examples of pretty much everything here that would be relevant to your problem: here
Also, note that you can't easily pull individual arguments from a parameter pack. You can use recursion to strip arguments off the front a few at a time, you can use them to initialise member variables in a constructor's initialisation list, you can check how many arguments are in the pack, you can specialise it (as we did for parameter_match), & you can pass the whole pack to a function that takes the right number of arguments, but I believe that's it at the moment. This can make them a bit more awkward than C-style varargs at times, despite being more efficient. However, if your ExecuteMethod()'s argument list consists of a function and its argument list, and nothing else, this isn't an issue. As long as the parameter match succeeds, we can just give the entire pack to the passed function, no questions asked. On that note, we can rewrite ExecuteMethod() into something like...
// Not sure what cx is, leaving it alone.
// Assuming you wanted ExecuteMethod to take parameters in the order (cx, function, function_parameter_list)...
// Parameter list match.
template<typename M, typename... Parameters>
static bool ExecuteMethodWorker(std::true_type x, JSContext* cx, M method, Parameters... params)
{
auto r = method(params...);
// ...
}
// Parameter list mismatch.
template<typename M, typename... Parameters>
static bool ExecuteMethodWorker(std::false_type x, JSContext* cx, M method, Parameters... params)
{
// Handle parameter type mismatch here.
// Omit if not necessary, though it's likely better to use it to log errors, terminate, throw an exception, or something.
}
// Caller.
template<typename M, typename... Parameters>
static bool ExecuteMethod(JSContext* cx, M method, Parameters... params)
{
return ExecuteMethodWorker(PChecker<M, Parameters...>{}, cx, method, params...);
}
Make sure to either prototype or define the worker functions before ExecuteMethod(), so the compiler can resolve the call properly.
(Apologies for any typoes I may have missed anywhere in there, I'm a bit tired.)
Edit: I've located the problem with passing references to a template. It seems that using templates to determine types does indeed remove reference-ness in and of itself, hence notation like template<typename T> void func(T&) for functions that take a reference. Sadly, I'm not yet sure how to fix this issue. I did, however, come up with a new version of PChecker that dynamically reflects types for any function that doesn't use reference types. So far, however, you still need to add references manually, and non-const references probably won't work properly for now.
namespace ParameterCheck {
namespace ParamGetter {
// Based on an answer from GManNickG ( https://stackoverflow.com/a/4693493/5386374 )
// Turn the type list into a single type we can use with std::is_same.
template<typename... Ts> struct variadic_typedef { };
// Generic case, to catch passed parameter types list.
template<typename... Ts> struct variadic_wrapper {
using type = variadic_typedef<Ts...>;
};
// Special case to catch void parameter types list.
template<> struct variadic_wrapper<> {
using type = variadic_typedef<void>;
};
// Generic case to isolate parameter list from function signature.
template<typename RT, typename... Ts> struct variadic_wrapper<RT (*)(Ts...)> {
using type = variadic_typedef<Ts...>;
};
// Special case to isolate void parameter from function signature.
template<typename RT> struct variadic_wrapper<RT (*)()> {
using type = variadic_typedef<void>;
};
} // namespace ParamGetter
template<typename... Ts> using PGetter = typename ParamGetter::variadic_wrapper<Ts...>::type;
// Declare class template.
template<typename... Ts> struct parameter_match;
// Actual class. Becomes either std::true_type or std::false_type.
template<typename F, typename... Ts> struct parameter_match<F, Ts...> : public std::integral_constant<bool, std::is_same<PGetter<F>, PGetter<Ts...> >{}> {};
// Put specialisations for functions with const references here.
} // namespace ParameterCheck
template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts...>;
See here.
--
Edit 2: Okay, can't figure out how to grab the passed function's parameter list and use it directly. It might be possible using tuples, perhaps using the rest of GManNickG's code (the convert_in_tuple struct), but I haven't looked into them, and don't really know how to grab the entire type list from a tuple at the same time, or if it's even possible. [If anyone else knows how to fix the reference problem, feel free to comment.]
If you're only using references to minimise passing overhead, and not to actually change data, you should be fine. If your code uses reference parameters to modify the data that the parameter is pointing to, however, I'm not sure how to help you. Sorry.
--
Edit 3: It looks like RChecker might not be as necessary for C++11 function forwarding, we can apparently use decltype([function call]) for that. So...
// caller2(), using decltype. Valid, as args... is a valid parameter list for f.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) -> decltype(f(args...)) {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
// decltype(f(args...)) would be problematic, since args... isn't a valid parameter list for f.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Parameter list mismatch." << std::endl;
return static_cast<RChecker<Func> >(0); // Make sure we don't break stuff.
}
// Wrapper to check for parameter mismatch.
// decltype(caller2(PChecker<Func, Ts...>{}, f, args...)) is valid, but would be more verbose than RChecker<Func>.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) -> RChecker<Func> {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
However, as noted, decltype can have issues when it can't find a function call that matches what it's passed exactly. So, for any case where the parameter mismatch version of caller2() is called, trying to use decltype(f(args...)) to determine return type would likely cause issues. However, I'm not sure if decltype(auto), introduced in C++14, would have that issue.
Also, in C++14-compatible compilers, it's apparently better to use decltype(auto) than just auto for automatic return type determination; auto doesn't preserve const-ness, volatile-ness, or reference-ness, while decltype(auto) does. It can be used either as a trailing return type, or as a normal return type.
// caller2(), using decltype(auto).
template<typename Func, typename... Ts> decltype(auto) caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
return f(args...);
}
decltype(auto) can also be used when declaring variables. See here for more information.
Edit 4: I believe I may have found a potential solution that preserves the passed function's parameter list properly, using functors. However, it may or may not create unwanted overhead, I'm not sure.
// Default functor.
template<typename... Ts>
struct Executor { };
// General case.
template<typename M, typename ReturnType, typename... Params>
struct Executor<M, ReturnType (*)(Params...)> {
public:
// Parameter match:
bool operator()(M method, Params... params) {
ReturnType r = method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Special case to catch void return type.
template<typename M, typename... Params>
struct Executor<M, void (*)(Params...)> {
public:
// Parameter match:
bool operator()(M method, Params... params) {
method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Also note that the "do { ... } while (false)" structure is used to swallow the trailing
// semicolon, so it doesn't inadvertently break anything; most compilers will optimise it
// out, leaving just the code inside.
// (Source: https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html )
// MSVC:
// #define ExecuteMethod(C, M, ...) \
// do { \
// Executor<decltype(&M), decltype(&M)> temp; \
// C = temp(M, __VA_ARGS__); \
// } while (false)
// GCC:
#define ExecuteMethod(C, M, ...) \
do { \
Executor<decltype(&M), decltype(&M)> temp; \
C = temp(M, ##__VA_ARGS__); \
} while (false)
In this case, you can use it as:
ExecuteMethod(return_value_holder, function_name, function_parameter_list);
Which expands to...
do {
Executor<decltype(&function_name), decltype(&function_name)> temp;
return_value_holder = temp(function_name, function_parameter_list);
} while (false);
With this, there's no need to manually go through the parameter pack and make sure each one matches the passed function's parameters. As the passed function's parameter list is quite literally built into Executor as Params..., we can simply overload the function call operator based on whether the arguments it was passed match Params... or not. If the parameters match the function, it calls the Parmas... overload; if they don't, it calls the Invalid_Params... overload. A bit more awkward than true reflection, IMO, but it seems to match everything properly.
Note that:
I'm not sure whether using functors liberally can cause any performance or memory use overhead. I'm... not all that familiar with them at the moment.
I don't know if it's possible to combine the general case and the "void return type" special case into a single functor. The compiler complained when I tried, but I'm not sure if it's because it isn't possible or because I was doing it wrong.
Considering #2, when modifying this version of ExecuteMethod()'s parameters, you have to modify it and both versions of Executor to match.
Like so, where JSContext* cx is added to the parameter list:
template<typename M, typename ReturnType, typename... Params>
struct Executor<M, ReturnType (*)(Params...)> {
public:
bool operator()(JSContext* cx, M method, Params... params);
};
template<typename M, typename... Params>
struct Executor<M, void (*)(Params...)> {
public:
bool operator()(JSContext* cx, M method, Params... params);
};
#define ExecuteMethod(C, cx, M, ...) \
do { \
Executor<decltype(&M), decltype(&M)> temp; \
C = temp(cx, M, ##__VA_ARGS__); \
} while (false)
This may be the solution, but it requires further testing to see if it has any negative impacts on performance. At the very least, it'll make sure const-ness and reference-ness is preserved by ExecuteMethod(), and it's a lot cleaner than my old ideas.
See here.
There are further improvements that can be made, however. As I'm out of space, see here.
Notes:
int16_t (a.k.a. std::int16_t) is in the header <cstdint>.
std::true_type and std::false_type are in the header <type_traits>.
It's difficult to tell from your description, but this is my closest interpretation to what you asked:
auto foo(int) { cout << "foo int" << endl; }
auto foo(float) { cout << "foo float" << endl; }
//... other foo overloads...
template <class T>
auto uber_function(T t)
{
foo(t);
}
template <class T, class... Args>
auto uber_function(T t, Args... args)
{
foo(t);
uber_function(args...);
}
auto main() -> int
{
uber_function(3, 2.4f);
return 0;
}
Of course this can be improved to take references, to make forwarding. This is just for you to have a starting point. As you weren't more clear, I can't give a more specific answer.

How to save variable number of arguments using variadic template arguments?

I would like to create template class which could store function pointer and arguments for a this function so the function can be later invoked with this arguments.
I would like to write this universally and not to depend on argument types or number.
Here is a scatch of the idea with the use of variadic templates of c++11:
template<class T, typename... Params>
class LazyEvaluation {
private:
// Function to be invoked later
T (*f)(Params...);
// Params for function f
Params... storedParams; // This line is not compilable!
bool evaluated;
T result;
public:
// Constructor remembers function pointer and parameters
LazyEvaluation(T (*f)(Params...),Params... params)
: f(f),
storedParams(params) //this line also cannot be compiled
{}
// Method which can be called later to evaluate stored function with stored arguments
operator T&() {
// if not evaluated then evaluate
if (! evaluated) {
result = f(storedParams...);
evaluated = true;
}
return result;
}
}
I would like to have at least the public interface of this class type safe if it is possible. Although getting this work at least somehow is more important.
I've managed to save the variable number of arguments somehow. But I wasn't able to pass them to the function f. I will write it to answers, but I would like you to think about your own solutions before you see my ugly not working attempt.
I am tring to compile the code above with Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012), but it would be best if a compiler independent solution would exist.
Thank you
Here is how I tried to solve it:
The parametr pack can be recursivle expanded and each parametr saved. Function store is supposed to do it. It uses one (two times overloaded) helper function.
template<typename T>
void storeHelperFunction(void*& memory, T last) {
*((T*)memory) = last;
memory = (void*)((char*)memory + sizeof(T));
}
template<typename T, typename... Params>
void storeHelperFunction(void*& memory, T first, Params... rest) {
storeHelperFunction(memory, first);
storeHelperFunction(memory, rest...);
}
template<typename... Params>
void store(void* memory, Params... args) {
// Copy of pointer to memory was done when passing it to this function
storeHelperFunction(memory, args...);
}
Function store takes a pointer to memory where the varialbe number of arguments is supposed to be saved.
The pointer can point to some dynamicly allocated memory or beter to the structure which size is equal to sizeof...(Params).
Such structure which has exactly any desiared size can be constructed using template metaprogramming:
template <int N>
struct allocatorStruct {
char byte1;
allocatorStruct<N-1> next;
};
template <>
struct allocatorStruct<1> {};
I am not sure what the standart says or how the other compilers than the microsoft one compile it. But using my compiler the sizeof(allocatorStruct) is equal to N for any N which is greater or equal to 1.
Hence allocatorStruct<sizeof...(Params)> has the same size as Params.
Another way to create something which has the same size as Params is to use a type char [sizeof...(Params)]. This has the disadvantage that the compiler passes only pointer to this array when you try to pass such array as argument.
That is why it is better to use allocatorStruct<sizeof...(Params)>.
And now the main idea:
When saving the function we can cast it to: T (*)(allocatorStruct<sizeof...(Params)>).
When saving the arguments for the function we can save them to struct of the type allocatorStruct<sizeof...(Params)>.
The size of the arguments is the same. Although the function pointer lies about the type of the function the function pointed to will get its data correctly.
At least I hoped. Depending on the calling convention I expected that the passed arguments can be reordered or wrong because of the difference between left to right saving arguments and right to left passing. But it wasn't the case. Using __cdecl calling convention only first argument was passed and the other was lost. With other calling conventions the program stoped working.
I didn't spend much time debugging it and looking to data in memory(on stack). Is it at least right way to go?
Simply use a lambda expression
// Some function.
int add(int a, int b) {
return a + b;
}
auto lazyFunc = [] { return add(1, 2); };
std::cout << lazyFunc() << std::endl; // Evaluate function and output result.
If you really want to create a class that only evaluates the function once (lazily), using variadic templates, you could do something like in the following code.
I also made the class as such that you don't have to create a new instance every time the parameters change. I use a std::tuple to store the given arguments, and compare against previously given arguments. If the arguments differ, then the function will be reevaluated.
Functions are passed around and stored using a std::function wrapper so I don't have to work with raw function pointers (yuck).
#include <iostream>
#include <functional>
#include <utility>
#include <tuple>
template <typename T>
class LazyEvaluation {};
template <typename ReturnType, typename... Params>
class LazyEvaluation<ReturnType(Params...)> {
private:
std::function<ReturnType(Params...)> func_;
ReturnType result;
std::tuple<Params...> oldParams; // Contains the previous arguments.
public:
explicit LazyEvaluation(std::function<ReturnType(Params...)> func)
: func_(std::move(func)) {}
template <typename... Args>
ReturnType operator() (Args&&... args) {
auto newParams = std::make_tuple(std::forward<Args>(args)...);
// Check if new arguments.
if (newParams != oldParams) {
result = func_(std::forward<Args>(args)...);
oldParams = newParams;
std::cout << "Function evaluated" << std::endl;
}
std::cout << "Returned result" << std::endl;
return result;
}
};
int main() {
auto f = [] (int a, int b) {
return a + b;
};
// Specify function type as template parameter.
// E.g. ReturnType(Param1Type, Param2Type, ..., ParamNType)
LazyEvaluation<int(int, int)> ld(f);
std::cout << ld(1, 2) << std::endl;
std::cout << ld(1, 2) << std::endl;
std::cout << ld(3, 4) << std::endl;
}
Output:
Function evaluated
Returned result
3
Returned result
3
Function evaluated
Returned result
7
Given the standard machinery for forming variadic index packs:
template <std::size_t... I> struct index_sequence {};
template <std::size_t N, std::size_t... I>
struct make_index_sequence : public make_index_sequence<N-1, N-1, I...> {};
template <std::size_t... I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
and to call functions with unpacked tuple arguments:
template <typename Function, typename... Types, std::size_t... I>
auto apply_(Function&& f, const std::tuple<Types...>& t, index_sequence<I...>)
-> decltype(std::forward<Function>(f)(std::get<I>(t)...)) {
return std::forward<Function>(f)(std::get<I>(t)...);
}
template <typename Function, typename... Types>
auto apply(Function&& f, const std::tuple<Types...>& t)
-> decltype(apply_(f, t, make_index_sequence<sizeof...(Types)>())) {
return apply_(f, t, make_index_sequence<sizeof...(Types)>());
}
This is fairly straightforward:
template<typename Function, typename... Params>
class LazyEvaluation {
private:
typedef decltype(std::declval<Function>()(std::declval<Params>()...)) result_type;
// Function to be invoked later
Function f;
// Params for function f
std::tuple<Params...> storedParams;
mutable bool evaluated;
union {
std::aligned_storage<sizeof(result_type)> space;
mutable result_type result;
};
// Method which can be called later to evaluate stored function with stored arguments
void evaluate() const {
// if not evaluated then evaluate
if (! evaluated) {
new (&result) result_type{apply(f, storedParams)};
evaluated = true;
}
}
public:
// Constructor remembers function pointer and parameters
LazyEvaluation(Function f, Params... params)
: f(std::move(f)),
storedParams(std::move(params)...),
evaluated(false)
{}
~LazyEvaluation() {
if (evaluated)
result.~result_type();
}
operator result_type&() {
evaluate();
return result;
}
operator const result_type& () const {
evaluate();
return result;
}
};
template <typename Function, typename... Params>
LazyEvaluation<Function, Params...>
make_lazy(Function&& f, Params&&... params) {
return {std::forward<Function>(f), std::forward<Params>(params)...};
}
I've used a union and placement new to store the result of evaluation so that it doesn't need to be a default-constructible type, and some mutable tricks so that a const LazyEvaluator can be converted as well as a non-const instance.

Create functors from functions with unknown argument count

I wrote a program in C++ & boost. Is it possible to write a template class producing functors from functions with an unknown number of arguments, e.g. my_call<func>(vector<variant>), where fun can be bool fun(string) or bool fun(int, int, string), etc.?
First, it is important to recognize that boost::variant<> is a class template that requires the list of all the possible types it can hold. So, you won't have just a vector<variant>, but rather a vector<variant<string, double>>, or vector<variant<int, double, string, my_class>>, and you won't be able to mix them.
This made me think you might want to use boost::any rather than boost::variant<>. Thus, I present here a solution that works with boost::variant and can be slightly modified to use boost::any, so you can pick the version you prefer.
To begin with, I must admit that the solution is simple to use but not so simple to understand, so I will have to introduce some machinery first. This machinery is common to both the variant-based and the any-based solution.
//=============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS
// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};
// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
// Declare primary template for index range builder
template <size_t MIN, size_t N, size_t... Is>
struct range_builder;
// Base step
template <size_t MIN, size_t... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_list<Is...> type;
};
// Induction step
template <size_t MIN, size_t N, size_t... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{
};
}
// Meta-function that returns a [MIN, MAX) index range
template<size_t MIN, size_t MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
The meta-class index_range allows defining compile-time sequences of integers. An interesting proposal have been made by Jonathan Wakely to standardize this kind of construct, so that this whole machinery would not be needed. For the moment, however, we have to hand code this as done above.
Now that we can build compile-time integer sequences, we can exploit variadic templates and argument unpacking to create a dispatching mechanism that translates a vector of variant arguments into a regular argument list. Notice how the concrete variant<> type must be provided as a template argument. This will not be needed for the solution based on any.
// Headers needed for the implementation of the dispatcher
#include <vector>
#include <functional>
#include <boost/variant.hpp>
// Just for convenience
using namespace std;
using boost::variant;
//============================================================================
// DISPATCHER IMPLEMENTATION
// Call dispatching mechanism: notice how the underlying variant type
// must be provided as a template argument (the first one)
template<typename VT, typename R, typename... Args>
struct dispatcher
{
template<typename F>
dispatcher(F f) : _f(f) { }
// The call operator which performs the variant dispatch
R operator () (vector<VT> const& v)
{
if (v.size() != sizeof...(Args))
{
// Wrong number of arguments provided!
return false;
}
// Delegates to internal function call: needed for deducing
// a sequence of integers to be used for unpacking.
index_range<0, sizeof...(Args)> indexes;
return do_call(v, indexes);
}
private:
// The heart of the dispatching mechanism
template<size_t... Is>
R do_call(vector<VT> const& v, index_list<Is...> indexes)
{
return _f((get_ith<Args>(v, Is))...);
}
// Helper function that extracts a typed value from the variant.
template<typename T>
T get_ith(vector<VT> const& v, size_t i)
{
return boost::get<T>(v[i]);
}
// Wrapper that holds the function to be invoked.
function<R(Args...)> _f;
};
// Helper function that allows deducing the input function signature
template<typename VT, typename R, typename... Args>
function<R (vector<VT> const&)> get_dispatcher(R (*f)(Args...))
{
dispatcher<VT, R, Args...> d(f);
return d;
}
Finally, a short demonstration of how you could use this. Suppose we have two test functions such as the ones below:
#include <iostream>
bool test1(string s, double d)
{
cout << s << " " << d << endl;
return true;
}
bool test2(int i1, int i2, string s1, string s2)
{
cout << i1 << " " << i2 << " " << s1 << " " << s2 << endl;
return true;
}
What we want is to invoke them by building a vector of variants and have it dispatched to the desired function. Once again, I must stress the fact that we need to specify the list of all the types our variant can hold. Here, I will assume these types are string, double, and int, but your program might work with different ones.
Also, the solution is based on std::function<> for realizing the type erasure that allows you creating functors of different types and yet invoke them uniformly. Thus, a convenience type definition for this std::function<> (which in turn depends on the variant<> type we use) is provided as well:
int main()
{
// A helper type definition for the variant
typedef variant<int, double, string> vt;
// A helper type definition for the function wrapper
typedef function<bool (vector<vt>)> dispatcher_type;
// Get a caller for the first function
dispatcher_type f1 = get_dispatcher<vt>(test1);
// Prepare arguments for the first function
vector<vt> v = {"hello", 3.14};
// Invoke the first function
f1(v);
// Get a caller for the second function
dispatcher_type f2 = get_dispatcher<vt>(test2);
// Prepare arguments for the second function
v.assign({1, 42, "hello", "world"});
// Invoke the second function
f2(v);
}
Since all dispatchers have type dispatcher_type, you can easily put them into a container. However, you must be aware of the fact that attempts to invoke a function with the wrong number of arguments will be detected only at run-time (it is impossible to know at compile-time how many elements an std::vector<> contains). Thus, proper care must be taken.
As promised, I will now slightly modify this solution to use boost::any rather than boost::variant. The advantage is that since boost::any can hold any value, it is not necessary to specify the list of the possible types which can be used as function arguments.
While the helper machinery is unchanged, the core dispatcher class template must be modified as follows:
#include <vector>
#include <functional>
#include <boost/any.hpp>
using namespace std;
using boost::any;
//=============================================================================
// DISPATCHER IMPLEMENTATION
template<typename R, typename... Args>
struct dispatcher
{
template<typename F>
dispatcher(F f) : _f(f) { }
// The call operator which performs the dispatch
R operator () (vector<any> const& v)
{
if (v.size() != sizeof...(Args))
{
// Wrong number of arguments provided!
return false;
}
// Delegates to internal function call: needed for deducing
// a sequence of integers to be used for unpacking.
index_range<0, sizeof...(Args)> indexes;
return do_call(v, indexes);
}
private:
// The heart of the dispatching mechanism
template<size_t... Is>
R do_call(vector<any> const& v, index_list<Is...> indexes)
{
return _f((get_ith<Args>(v, Is))...);
}
// Helper function that extracts a typed value from the variant.
template<typename T>
T get_ith(vector<any> const& v, size_t i)
{
return boost::any_cast<T>(v[i]);
}
// Wrapper that holds the function to be invoked.
function<R(Args...)> _f;
};
// Helper function
template<typename R, typename... Args>
function<R (vector<any> const&)> get_dispatcher(R (*f)(Args...))
{
dispatcher<R, Args...> d(f);
return d;
}
As you see, the VT template argument has vanished. In particular, it is possible to call get_dispatcher without explicitly specifying any template argument. Using the same test functions we have defined for the variant-based solution, here is how you would adapt the main() routine:
int main()
{
// Helper type definition
typedef function<bool (vector<any>)> dispatcher_type;
// Get a caller for the first function
dispatcher_type f1 = get_dispatcher(test1);
// Get a caller for the second function
dispatcher_type f2 = get_dispatcher(test2);
// Prepare arguments for the first function
vector<any> v = {string("hello"), 3.14};
// Invoke the first function
f1(v);
// Prepare arguments for the second function
v.assign({1, 42, string("hello"), string("world")});
// Invoke the second function
f2(v);
}
The only disadvantage is that with boost::any you cannot assign string literals explicitly, because string literals are of type char [], and arrays cannot be used to initialize objects of type any:
any a = "hello"; // ERROR!
Thus, you have to either wrap them into string objects, or explicitly convert them to a pointer to char const*:
any a = string("hello"); // OK
any b = (char const*)"hello"; // OK
If this is not a huge problem for you, it's probably better to go for this second solution.