Experimental dispatching with std::apply - c++

I would like to have a general function 'request' which could accept a tuple of any number of arguments. I want the 'request' function to dispatch the call to a number of other functions, depending on the number of arguments (of course the interface of the functions must match).
I wrote this code, but it only works if I call function of one type inside the 'request'. As soon as I uncomment the dispatching mechanism (else -> dispatch to fun5) everything stops compiling.
The problem is that the body of function 'request', created for the case of dispatching to function with two parameters, must compile, and then there is a function with 5 arguments inside it, to which the tuple of 2 arguments cannot be applied. And vice versa. Classic problem with templates. I know that I could somehow apply SFINAE concept to this problem, but I somehow don't know how (I am not as strong in MPL programming).
#include <iostream>
#include <experimental/tuple>
enum class type { v2, v5 };
void fun2(int i1, int i2)
{
std::cout << "fun2 called, i1 = " << i1 << ", i2 = " << i2 << std::endl;
}
void fun5(bool b1, float f1, int i, char c, bool b2)
{
std::cout << "fun5 called with: " << std::boolalpha << b1 << ", " << f1 << ", " << i << ", " << c << ", " << b2 << std::endl;
}
template <typename F, typename... T>
void dispatch(F f, T... args)
{
std::experimental::apply(f, args...);
}
template <typename... T>
void request(type t, T... args)
{
if (t == type::v2)
dispatch(fun2, args...);
// else
// dispatch(fun5, args...);
}
int main()
{
auto v2 = std::make_tuple(1,1);
request(type::v2, v2);
// auto v5 = std::make_tuple(true, 1.5f, 3, 'c', false);
// request(type::v5, v5);
}
How can I make this work? What kind of dispatching mechanism I need here to make this work?

Instead of using an enumeration to select what to do, I suggest you use tags and tag structures instead. Then you can simply select the right dispatch function using simple function overloading.
Perhaps something like
namespace type
{
struct v2_tag {};
struct v5_tag {};
v2_tag v2;
v5_tag v5;
}
template<typename... T>
void request(type::v2_tag, T... args)
{
dispatch(fun2, args...);
}
template<typename... T>
void request(type::v5_tag, T... args)
{
dispatch(fun5, args...);
}
The rest of the code stays the same.

An alternative to tag dispatch (which I highly recommend as per #Some programmer dude) would be to create your own function object that accepts a type as a non-type template argument so that we can take advantage of constexpr if:
template<type t>
struct request
{
template<class... T>
void operator()(T... args) const
{
if constexpr(t == type::v2)
dispatch(fun2, args...);
else
dispatch(fun5, args...);
}
};
The downside is that you have to construct one to make your call:
auto v2 = std::make_tuple(1, 1);
request<type::v2>()(v2);
auto v5 = std::make_tuple(true, 1.5f, 3, 'c', false);
request<type::v5>()(v5);
Demo
A variation on this approach is to instead have a static apply function in your request class like so:
template<type t>
struct request{
template<class... T>
static void apply(T... args){/*..*/}
}
And then a call to it would look like this instead (no funky empty braces):
request<type::v2>::apply(v2);
Demo2

Related

GCC macro to print all function arguments

I need some macro or other way to print current function and its arguments. For the function name it is easy, as we can use e.g. __PRETTY_FUNCTION__. Is there some macro that holds function arguments? Or can you use va_list and va_start for non-variadic functions?
Something similar to __VA_ARGS__ but for a regular function, not macros. I don't mind taking this out of some symbol table etc. as long as it works.
To do something like this:
#define FUNC_ENTER printName(__PRETTY_FUNCTION__); printArgs(__WHAT_IM_MISSING__);
void someFunc(int a, int b)
{
FUNC_ENTER;
// ... rest of the function ...
}
void main()
{
someFunc(5, 10);
// Should print "Entering 'someFunc' with '5 10'" or something similar.
}
P.S.1. I know I could make it work with writing FUNC_ENTER(a, b) - but I'd like to save myself typing the arguments
P.S.2. Don't suggest GCC's __cyg_profile_func_enter - as I don't want this macro for every function.
Note: the following is all specific to C++.
I don't know of a clean way of doing this inside the function in question. But you can pretty easily do it as a wrapper for the function, on this general order:
#include <iostream>
// just a couple functions with different number/types of arguments
// to demonstrate invoking
int someFunc(int a, int b) {
return a + b;
}
void otherFunc(std::string const &a, int b, long long c) {
std::cout << "a: " << a << ", b: " << b << ", c: " << c;
}
// Print out arguments, then invoke function:
template <class F, typename ...Args>
auto invoke(F f, Args && ...args) {
(std::cout << "Args: " << ... << args) << "\n";
return f(std::forward<Args>(args)...);
}
int main() {
std::cout << invoke(someFunc, 1, 2) << "\n";
invoke(otherFunc, "first", 2, 3);
std::cout << "\n";
}
If you want to "hide" the implementation from the user so they only have to call an ordinary looking function, you can pretty easily add a little wrapper for each individual function, something along this line:
namespace {
// this is the actual implementation, hidden from the user
void function_implementation(/* whatever args*/) {
// ...
}
}
// this is all the user sees--print args, then invoke implementation.
// For each wrapper, you edit the name you want the user to see, and the
// implementation it invokes.
template <typename ...Args>
void function(Args && ...args) {
std::cout << __PRETTY_FUNCTION__;
invoke(function_implementation, std::forward<Args>(args)...);
}
As this code stands, it has one minor difficulty: it doesn't insert a delimiter between each argument as it's printing them out. If you need that, you can (for one possibility) expand the parameter pack recursively instead of using a fold expression:
template <class T>
void print(T const &t) {
std::cout << t << "\t";
}
template<typename T, typename... Args>
void print(T n, Args ... args) {
print(n);
print(args...);
std::cout << "\n";
}
template <class F, typename ...Args>
auto invoke(F f, Args && ...args) {
print(std::forward<Args>(args)...);
return f(std::forward<Args>(args)...);
}

Is it possible to store lambdas with different signatures in a std::vector and execute them (with their respective arguments) in a function?

I am creating a class that allows me to store lambdas that need to be executed (in order) at a point in the future.
class Promise{
private:
//snip//
std::vector<std::function<void()>> lchain;
public:
//snip//
void then(const std::function<void()> &f){
if (this->resolved) {//If the promise is resolved we just call the newly added function, else we add it to the lchain queue that will be processed later
f();
return;
}
lchain.push_back(f);
}
void launch(){
this->resolved = true;
for (auto &fun: this->lchain)
fun();
}
}
It is obvious that it will only work with lambdas with a signature like [&](){} but some of the tasks need to work with an arbitrary number of parameters of arbitrary types (both, parameters and types are known in advance, when the function is added to the queue).
An example driver program that currently works is
int main(){
Promise* p = new Promise([](){
std::cout << "first" << std::endl;
})->then([](){
std::cout << "second" << std::endl;
});
Promise->launch(); //In my code promise chains are picked up by worker threads that will launch them.
}
An example program I would like to execute:
int main(){
Promise* p = new Promise([](){
return 5;
})->then([](int n){
return n*n;
})->then([](int n){
std::cout << n << std::endl; //Expected output: 25
});
Promise->launch();
}
Things that I am struggling to do:
Storing lambdas of mixed signatures in a std::vector
Making the then() method call f with the arguments associated with f
Making the then() function return the result of f so it can be fed to the next lambda in the chain (preferably binding it before storing the lambda in the vector)
I have been searching in stackoverflow the whole day but the closest I got was this but I would like something that can be done in the then() method to simplify the program code as it would be a pain to bind every single lambda before calling the then() method.
I have something that I think does what you want. I'll start with an example and then introduce the implementation.
int main(){
Promise p([] {
return 5;
});
p.then([](int n) {
return n*n;
}).then([](int n) {
std::cout << n << '\n';
});
p.launch();
struct A { int n; };
struct B { int n; };
struct C { int n; };
Promise q([](A a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{2};
});
q.then([](B b) {
std::cout << "B " << b.n << '\n';
return C{3};
}).then([](C c) {
std::cout << "C " << c.n << '\n';
});
q.launch(A{1}, 111);
Promise<B(A, int)> r([](auto a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{5};
});
r.then([](auto b) {
std::cout << "B " << b.n << '\n';
return C{6};
}).then([](auto c) {
std::cout << "C " << c.n << '\n';
});
r.launch(A{4}, 222);
}
This outputs:
25
A 1 111
B 2
C 3
A 4 222
B 5
C 6
Some drawbacks:
Calling then after the promise has been resolved doesn't automatically call the function. Things get confusing in that situation and I'm not even sure if it's possible.
You can't call then multiple times on the same promise. You have to build a chain and call then on the result of the previous then.
If any of those drawbacks make this unusable, then you can stop reading this humongous answer.
The first thing we need is a way of getting the signature of a lambda. This is only used for the deduction guide so it isn't strictly necessary for the core concept to work.
template <typename Func>
struct signature : signature<decltype(&Func::operator())> {};
template <typename Func>
struct signature<Func *> : signature<Func> {};
template <typename Func>
struct signature<const Func> : signature<Func> {};
template <typename Ret, typename... Args>
struct signature<Ret(Args...)> {
using type = Ret(Args...);
};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...)> : signature<Ret(Args...)> {};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...) const> : signature<Ret(Args...)> {};
template <typename Func>
using signature_t = typename signature<Func>::type;
The next thing we need is a base class. We know the next promise must accept the return type of the current promise as an argument. So we know the argument type of the next promise. However, we don't know what the next promise will return until then is called so we need a polymorphic base to refer to the next promise.
template <typename... Args>
class PromiseBase {
public:
virtual ~PromiseBase() = default;
virtual void launch(Args...) = 0;
};
Now we have the Promise class itself. You can construct a promise with a function. As I alluded to above, a promise stores a pointer to the next promise in the chain. then constructs a promise from the given function and stores a pointer to it. There is only one next pointer so you can only call then once. There's an assertion to make sure this doesn't happen. launch calls the stored function and passes the result to the next promise in the chain (if there is one).
template <typename Func>
class Promise;
template <typename Ret, typename... Args>
class Promise<Ret(Args...)> : public PromiseBase<Args...> {
public:
template <typename Func>
explicit Promise(Func func)
: handler{func} {}
template <typename Func>
auto &then(Func func) {
assert(!next);
if constexpr (std::is_void_v<Ret>) {
using NextSig = std::invoke_result_t<Func>();
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
} else {
using NextSig = std::invoke_result_t<Func, Ret>(Ret);
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
}
}
void launch(Args... args) override {
if (next) {
if constexpr (std::is_void_v<Ret>) {
handler(args...);
next->launch();
} else {
next->launch(handler(args...));
}
} else {
handler(args...);
}
}
private:
using NextPromise = std::conditional_t<
std::is_void_v<Ret>,
PromiseBase<>,
PromiseBase<Ret>
>;
std::unique_ptr<NextPromise> next;
std::function<Ret(Args...)> handler;
};
Finally, we have a deduction guide.
template <typename Func>
Promise(Func) -> Promise<signature_t<Func>>;
Here's an online demo.

Is it possible to do this lambda event manager in C++?

I want to write an event manager that supports passing an arbitrary number of arguments. To show you the form, here is an example. Please note that one goal is to not need a class definition for every event. Instead, events are represented by string names. First, lets register four listeners to the same event. They differ in the number of parameters they accept.
Events events;
events.listen("key", [=] {
cout << "Pressed a key." << endl;
});
events.listen("key", [=](int code) {
cout << "Pressed key with code " << code << "." << endl;
});
events.listen("key", [=](int code, string user) {
cout << user << " pressed key with code " << code << "." << endl;
});
events.listen("key", [=](int code, string user, float duration) {
cout << user << " pressed key with code " << code << " for " << duration
<< " seconds." << endl;
});
events.listen("key", [=](string user) {
cout << user << " pressed a key." << endl;
});
Now fire the event with some arguments. events.fire("key", {42, "John"}); This should call registered lambdas that match some or all of the arguments. For example, this call should produce the following result for the five listeners we registered.
Print "Pressed a key."
Print "Pressed key with code 42."
Print "John pressed key with code 42."
Throw exception because listener doesn't match signature.
Throw exception because listener doesn't match signature.
Is it possible to achieve this behavior in C++? If so, how can I store the different callbacks in a collection while still being able to cast them back for calling with different numbers of parameters? I think this task is not easy so every hint helps.
I agree with Luc's point that a type-safe approach is probably more appropriate, but the following solution does more or less what you want, with a few limitations:
Argument types must be copyable;
Arguments are always copied, never moved;
A handler with N parameters is invoked if and only if the types of the first N arguments to fire() match exactly the types of the handler's parameters, with no implicit conversions being performed (e.g. from string literal to std::string);
Handlers cannot be functors with more than one overloaded operator ().
This is what my solution eventually allows you to write:
void my_handler(int x, const char* c, double d)
{
std::cout << "Got a " << x << " and a " << c
<< " as well as a " << d << std::endl;
}
int main()
{
event_dispatcher events;
events.listen("key",
[] (int x)
{ std::cout << "Got a " << x << std::endl; });
events.listen("key",
[] (int x, std::string const& s)
{ std::cout << "Got a " << x << " and a " << s << std::endl; });
events.listen("key",
[] (int x, std::string const& s, double d)
{ std::cout << "Got a " << x << " and a " << s
<< " as well as a " << d << std::endl; });
events.listen("key",
[] (int x, double d)
{ std::cout << "Got a " << x << " and a " << d << std::endl; });
events.listen("key", my_handler);
events.fire("key", 42, std::string{"hi"});
events.fire("key", 42, std::string{"hi"}, 3.14);
}
The first call to fire() will produce the following output:
Got a 42
Got a 42 and a hi
Bad arity!
Bad argument!
Bad arity!
While the second call will produce the following output:
Got a 42
Got a 42 and a hi
Got a 42 and a hi as well as a 3.14
Bad argument!
Bad argument!
Here is a live example.
The implementation is based on boost::any. The heart of it is the dispatcher functor. Its call operator takes a vector of type-erased arguments and dispatches them to the callable object with which it is constructed (your handler). If the arguments type don't match, or if the handler accepts more arguments than provided, it just prints an error to the standard output, but you can make it throw if you wish or do whatever you prefer:
template<typename... Args>
struct dispatcher
{
template<typename F> dispatcher(F f) : _f(std::move(f)) { }
void operator () (std::vector<boost::any> const& v)
{
if (v.size() < sizeof...(Args))
{
std::cout << "Bad arity!" << std::endl; // Throw if you prefer
return;
}
do_call(v, std::make_integer_sequence<int, sizeof...(Args)>());
}
private:
template<int... Is>
void do_call(std::vector<boost::any> const& v, std::integer_sequence<int, Is...>)
{
try
{
return _f((get_ith<Args>(v, Is))...);
}
catch (boost::bad_any_cast const&)
{
std::cout << "Bad argument!" << std::endl; // Throw if you prefer
}
}
template<typename T> T get_ith(std::vector<boost::any> const& v, int i)
{
return boost::any_cast<T>(v[i]);
}
private:
std::function<void(Args...)> _f;
};
Then there are a couple of utilities for creating dispatchers out of a handler functor (there is a similar utility for creating dispatchers out of function pointers):
template<typename T>
struct dispatcher_maker;
template<typename... Args>
struct dispatcher_maker<std::tuple<Args...>>
{
template<typename F>
dispatcher_type make(F&& f)
{
return dispatcher<Args...>{std::forward<F>(f)};
}
};
template<typename F>
std::function<void(std::vector<boost::any> const&)> make_dispatcher(F&& f)
{
using f_type = decltype(&F::operator());
using args_type = typename function_traits<f_type>::args_type;
return dispatcher_maker<args_type>{}.make(std::forward<F>(f));
}
The function_traits helper is a simple trait to figure out the types of the handler so we can pass them as template arguments to dispatcher:
template<typename T>
struct function_traits;
template<typename R, typename C, typename... Args>
struct function_traits<R(C::*)(Args...)>
{
using args_type = std::tuple<Args...>;
};
template<typename R, typename C, typename... Args>
struct function_traits<R(C::*)(Args...) const>
{
using args_type = std::tuple<Args...>;
};
Clearly this whole thing won't work if your handler is a functor with several overloaded call operators, but hopefully this limitation won't be too severe for you.
Finally, the event_dispatcher class allows you storing type-erased handlers in a multimap by calling listen(), and invokes them when you call fire() with the appropriate key and the appropriate arguments (your events object will be an instance of this class):
struct event_dispatcher
{
public:
template<typename F>
void listen(std::string const& event, F&& f)
{
_callbacks.emplace(event, make_dispatcher(std::forward<F>(f)));
}
template<typename... Args>
void fire(std::string const& event, Args const&... args)
{
auto rng = _callbacks.equal_range(event);
for (auto it = rng.first; it != rng.second; ++it)
{
call(it->second, args...);
}
}
private:
template<typename F, typename... Args>
void call(F const& f, Args const&... args)
{
std::vector<boost::any> v{args...};
f(v);
}
private:
std::multimap<std::string, dispatcher_type> _callbacks;
};
Once again, the whole code is available here.
one goal is to not need a class definition for every event.
That’s a good sign that you want something else than C++ for your purposes, since it has no dynamic reflection capabilities. (If you do use something more dynamic but still need to interface with C++, you would need to bridge the gap though, so this answer may or may not still be useful for that.)
Now while it is possible to build a (limited) dynamic system, you should ask yourself if it is what you really want to do. E.g. if you ‘close the world’ of events and their callback signatures, you would retain a lot of type-safety:
// assumes variant type, e.g. Boost.Variant
using key_callback = variant<
function<void(int)> // code
, function<void(int, string)> // code, user
, function<void(int, string, float)> // code, user, duration
, function<void(string)> // user
>;
using callback_type = variant<key_callback, …more event callbacks…>;
In the spirit of sticking to your requirement though, here’s how to store any† callback, and still be able to call it:
using any = boost::any;
using arg_type = std::vector<any>;
struct bad_signature: std::exception {};
struct bad_arity: bad_signature {};
struct bad_argument: bad_signature {
explicit bad_argument(int which): which{which} {}
int which;
};
template<typename Callable, typename Indices, typename... Args>
struct erased_callback;
template<typename Callable, std::size_t... Indices, typename... Args>
struct erased_callback<Callable, std::index_sequence<Indices...>, Args...> {
// you can provide more overloads for cv/ref quals
void operator()(arg_type args)
{
// you can choose to be lax by using <
if(args.size() != sizeof...(Args)) {
throw bad_arity {};
}
callable(restore<Args>(args[Indices], Indices)...);
}
Callable callable;
private:
template<typename Arg>
static Arg&& restore(any& arg, int index)
{
using stored_type = std::decay_t<Arg>;
if(auto p = boost::any_cast<stored_type>(&arg)) {
return std::forward<Arg>(*p);
} else {
throw bad_argument { index };
}
}
};
template<
typename... Args, typename Callable
, typename I = std::make_index_sequence<sizeof...(Args)>
>
erased_callback<std::decay_t<Callable>, I, Args...> erase(Callback&& callback)
{ return { std::forward<Callback>(callback) }; }
// in turn we can erase an erased_callback:
using callback_type = std::function<void(arg_type)>;
/*
* E.g.:
* callback_type f = erase<int>([captures](int code) { ... });
*/
Coliru demo.
If you have a type trait that can guess the signature of a callable type, you can write an erase that uses it (while still allowing the user to fill it in for those cases where it can’t be deduced). I’m not using one in the example because that’s another can of worms.
†: ‘any‘ meaning any callable object accepting some numbers of copyable arguments, returning void—you can relax the requirements on arguments by using a move-only wrapper similar to boost::any

c++11 bind and apply?

std::bind is sometimes described as "partial application". Any reasons why when all parameters of a function are bound, the function itself isn't applied?
For example, the following code prints nothing.
#include <functional>
#include <iostream>
using namespace std;
using namespace std::placeholders;
void f(int a,string b) {cout << a << b << endl;};
int main() {
bind(bind(f,1,_1),"Hi!");
return 0;
}
Is there a way to write a bind variant that can apply the function when all parameters are fixed?
--Update--
I understand from the responses now that std::bind is not exactly partial application. So, on the second part of the question, how can I write something like std::bind but does partial application.
I know bind(bind(f,1,_1),"Hi!")() will call the final 0-ary function and return the result value (printing 1Hi in the example). Is it possible to do template programming to call the function call operator () in the terminal case of bind?
In other words, is it possible to write a function bind1:
template< class R, class F, class... Args >
bind1( F f, Args... args )
, such that when std::is_placeholder<T>::value == 0 for each member of args,
bind1() can, in addition to what std::bind() does, call the operator()?
A function with no arguments is just a value in Haskell. You don't call it, you just use it. Since there are no side effects, there is no observable difference.
In OCaml there are simply no parameter-less functions, to get something like that you need to add a dummy unit argument.
Not so in C++. C++, unlike Haskell and OCaml, maintains clear difference between f and f(). bind gives you the former because you can always turn it into the latter by adding (). You can write your own wrapper for bind that does just that quite easily. Going the other way around would be a tad more difficult.
Here's a possible implementation of such wrapper:
#include <functional>
#include <utility>
#include <iostream>
template <typename T>
struct is_noargs_callable {
private:
typedef char(&yes)[1];
typedef char(&no)[2];
template<typename U>
static yes test(decltype((std::declval<U>())())*);
template<typename>
static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template <typename T>
struct is_noargs_callable<T()> {
static const bool value = true;
};
template <typename T>
struct is_noargs_callable<T(...)> {
static const bool value = true;
};
template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<is_noargs_callable<T>::value, decltype(t())>::type
{
return t();
}
template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<!is_noargs_callable<T>::value, T>::type
{
return t;
}
template <typename... Args>
auto apply(Args&&... args) -> decltype(call_me_if_you_can(std::bind(args...))) {
return call_me_if_you_can(std::bind(args...));
}
// testing
void foo(int a, int b, int c) { std::cout << "foo(" << a << "," << b << "," << c << ")"; }
int main ()
{
using namespace std::placeholders;
std::cout << "zero : " ; apply(foo, _1, _2, _3); std::cout << " : " ; apply(foo, _1, _2, _3)(1,2,3); std::cout << std::endl;
std::cout << "one : " ; apply(foo, 1, _1, _2); std::cout << " : " ; apply(foo, 1, _1, _2)(2,3); std::cout << std::endl;
std::cout << "two : " ; apply(foo, 1, 2, _1); std::cout << " : " ; apply(foo, 1, 2, _1)(3); std::cout << std::endl;
std::cout << "three: " ; apply(foo, 1, 2, 3); std::cout << " : "; /* nothing to test here */ std::cout << std::endl;
}
However, killing the difference between f and f() just in this one place does not IMHO contribute to the overall consistency of C++ programming. If you don't like the distinction, kill it everywhere (or just use you a Haskell for great good).
No sources for this, just my opinion.
The reason that wasn't done is because there is no reason to do it. If you know all of the input to the function, just call it.
And if you were doing something with templates that resulted in this, you would need to write all of the code consistently anyway. A special case here would only require a special case somewhere else.

How do I determine the number of parameters of a std::function?

I have the following problem. Say you want to write a generic function that can take a lambda expression. I understand that if the parameter is of type std::function, then I could not only use lambdas, but also functions and even pointers to functions. So at a first step, I did the following:
void print(std::function<void(int, int)> fn) {
fn(1,2);
}
int main() {
print([](int i, int j) { std::cout << j <<','<<i<<'\n'; });
return 0;
}
Now the problem is that I want to make this function generic, meaning that I don't want the lambda expression to have only two parameters.
So I tried changing the signature of the print function to something more generic like:
template <class function_type>
void print(function_type fn);
But now the problem is that the function takes ANY object and I'm not ok with that.
But the main problem is that, I have no idea how many parameters the object fn can accept.
So in a way I'm looking for a compile time way to determine how many arguments fn has, and if possible to change the type of fn to std::function. And then, given that I know the number of parameters that fn accepts, is there a generic way to pack an arbitrary number of parameters to be passed to fn? I don't even know if this is possible within C++11. What I mean is that given the number of arguments, is there a way to pack parameters to pass to fn? So that if there are two arguments, then I would call
fn(arg1, arg2);
if there are three:
fn(arg1, arg2, arg3);
and so on.
Thank you all for your insight.
aa
The following snippets might be useful.
This gives the number of arguments that a std::function takes
template <typename Signature>
struct count_args;
template <typename Ret, typename... Args>
struct count_args<std::function<Ret(Args...)>> {
static constexpr size_t value = sizeof...(Args);
};
For example the following code compiles (clang 3.2, gcc 4.7.2 and icc 13.1.0)
static_assert(count_args<std::function<void() >>::value == 0, "Ops!");
static_assert(count_args<std::function<void(int) >>::value == 1, "Ops!");
static_assert(count_args<std::function<void(int, int)>>::value == 2, "Ops!");
As far as I understand, you want to call the function object passing the correct number of arguments, right? Then for each argument we need to provide a value which is convertible to its type. A solution with this generality is very hard (or even impossible). Hence, I'll present two alternatives.
1 Each argument is a value initialized object of its type. (This is what ecatmur suggested.)
template <typename Ret, typename... Args>
Ret call(const std::function<Ret(Args...)>& f) {
return f(Args{}...); // for the intel compiler replace {} with ()
}
2 A fixed value is given and all the arguments are implicitly initialized from this value:
template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<sizeof...(Args) == sizeof...(Vals), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val&, const Vals&... vals) {
return f(vals...);
}
template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<(sizeof...(Args) > sizeof...(Vals)), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val& val, const Vals&... vals) {
return call(f, val, val, vals...);
}
The three overloads are unambiguous and can be used as the following examples show:
{
std::function<char()> f = []() -> char {
std::cout << "f() ";
return 'A';
};
std::cout << call(f) << std::endl; // calls f()
std::cout << call(f, 0) << std::endl; // calls f()
}
{
std::function<char(int)> f = [](int i) -> char {
std::cout << "f(" << i << ") ";
return 'B';
};
std::cout << call(f) << std::endl; // calls f(0)
std::cout << call(f, 1) << std::endl; // calls f(1)
}
{
std::function<char(int, int)> f = [](int i, int j) -> char {
std::cout << "f(" << i << "," << j << ") ";
return 'C';
};
std::cout << call(f) << std::endl; // calls f(0, 0)
std::cout << call(f, 2) << std::endl; // calls f(2, 2)
}
Yes you can pack as many parameters to fn as you wish using variadic templates.
template <class function_type, class... Args>
void print(function_type fn, Args... args)
{
//Call fn with args
fn(std::forward<Args>(args...));
}
To find out how many args there are in the parameter pack, you can use sizeof...(args).
To determine the signature of a callable, you can use the solution from Inferring the call signature of a lambda or arbitrary callable for "make_function". You can then package the callable into a std::function, or create a tag and use parameter inference:
template<typename T> struct tag {};
template<typename F, typename... Args>
void print_impl(F &&fn, tag<void(Args...)>) {
fn(Args{}...);
}
template<typename F>
void print(F &&fn) {
print_impl(std::forward<F>(fn), tag<get_signature<F>>{});
}
Note this uses value-initialised arguments; if you want anything more complex you can build a std::tuple<Args...> and pass that along, invoking it per "unpacking" a tuple to call a matching function pointer.