C++ need a container to store user defined function - c++

I am trying to create a interface between user defined function and data. Let's say I need to create a function called MapFun(), input of MapFun() includes user defined function (UDF) handle and UDF inputs.
void userFun1(Data data, int in1, int in2){
// user defined function 1;
}
void userFun2(Data data, int in1, int in2, std::string s){
// user defined function 2;
}
// ...
// apply user function 1 on data
MapFun(#userFun1, data, 3, 4);
// apply user function 2 on data
MapFun(#userFun2, data, 1, 2, "algorithm");
User will write userFun and apply it with MapFun(). So, how to design MapFun()? User function may have different inputs and the signature can't be predicted. In addition, MapFun() won't evaluate userFun immediately, instead, it stores all userFun and do a lazy evaluation.
Any suggestions are greatly appreciated.

User function may have different inputs and the signature can't be predicted.
It seems a typical works for variadic templates
In addition, MapFun() won't evaluate userFun immediately, instead, it stores all userFun and do a lazy evaluation.
Not sure to understand but I suppose you can obtain what do you want using std::bind() or, maybe better, with lambda functions.
I propose the following C++14 variadic template MapFun() function that return a lambda function that capture both user-function and argument. That function can be executed later.
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
The following is a full working example
#include <iostream>
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
void userFun2 (int i1, int i2, std::string const & s)
{ std::cout << "uf2, " << i1 << ", " << i2 << ", " << s << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
auto l2 = MapFun(userFun2, 3, 4, "five");
l2();
l1();
}

If I understand right, you just want to store a function and a set of arguments so that they can be called later. This is exactly what std::bind does (anyway, the simplest thing it does). In fact, you could possibly just use std::bind directly in place of your MapFun:
auto func1 = std::bind(userFun1, data, 3, 4);
auto func2 = std::bind(userFun2, data, 1, 2, "algorithm");
// ... and later,
func1();
func2();
Note the auto in those: you can't (portably) write the type of any object returned by std::bind, and those two example objects will have different types. But both of those would implicitly convert to the common type std::function<void()>. You can store a bunch of std::function<void()> objects in nearly any container type you want, to be used later:
std::map<unsigned int, std::function<void()>> func_map;
func_map[0] = std::bind(userFun1, data, 3, 4);
func_map[1] = std::bind(userFun2, data, 1, 2, "algorithm");
// ...
auto func_iter = func_map.find(key);
if (func_iter != func_map.end() && func_iter->second) {
(func_iter->second)();
}
Of course, if you want to use your name of the function, and/or if you need the explicit common return type to work well with other templates or something, you can just wrap std::bind:
template <class F, class... Args>
std::function<void()> MapFun(F&& f, Args&&... args) {
return std::bind<void>(std::forward<F>(f), std::forward<Args>(args)...);
}
Or if your MapFun is supposed to store the callable object inside some class member container or something, not just create and return one (it's not clear), it can of course do that by using std::bind and then adding the result to whatever container you need.

If you only need to backport std::invoke from C++17, well, its simplest form is quite straightforward:
template<class F, class... Args> decltype(auto) invoke(F &&f, Args &&...args) {
return ::std::forward<F>(f)(::std::forward<Args>(args)...);
}

Related

Storing a function reference with variable arguments in a data member in C++

I want to store a function reference with a variable number of arguments in a class data member and call it later as follows:
auto my_action = new ExecuteAction("Add", add, 1, 2);
std::vector<ExecuteAction *> execute_actions;
execute_actions.push_back(my_action);
// ...
auto my_action_retrieved = execute_actions.at(0);
my_action_retrieved->execute();
Note that add() is e.g. defined as follows:
void add(int a, int b) {
std::cout << a + b << std::endl;
}
The closest solution I could get so far is the following:
template<typename Function, typename... Arguments>
class ExecuteAction {
static_assert(!(std::is_rvalue_reference_v<Arguments> && ...));
std::string option_name;
Function function;
std::tuple<Arguments...> arguments;
public:
template<typename ForwardFunction, typename... ForwardArguments,
typename = std::enable_if_t<(std::is_convertible_v<ForwardArguments &&, Arguments> && ...)>>
explicit ExecuteAction(std::string &option_name,
ForwardFunction &&function,
ForwardArguments &&... arguments)
: function(std::forward<ForwardFunction>(function)),
arguments{std::forward<ForwardArguments>(arguments)...} {
this->option_name = option_name;
}
void execute() {
std::apply(function, arguments);
}
};
template<typename Function, typename... Arguments>
auto make_execute_action(std::string option_name, Function &&function, Arguments &&... arguments) {
return new ExecuteAction<std::decay_t<Function>, std::remove_cv_t<std::remove_reference_t<Arguments>>...>
(option_name, std::forward<Function>(function), std::forward<Arguments>(arguments)...);
}
This code can successfully be called as follows:
auto add_action = make_execute_action("Add", [](int a, int b) {
std::cout << a + b << std::endl;
}, 1, 2);
add_action->execute();
This solution however has the following problems:
Functions have to be passed by lambda expression but I want to pass function references (like in the example above)
Using a generic std::vector doesn't seem possible since the template parameters need to be specifically defined
Is there an implementation in C or up till C++20 which satisfies my requirements?

C++ iterate template parameters

It's possible to fill the appropriate registers of a virtual machine based on the argument list and some logic using a C++17 fold, like so:
https://github.com/fwsGonzo/libriscv/blob/master/lib/libriscv/machine_vmcall.hpp#L35
https://github.com/fwsGonzo/libriscv/blob/master/lib/libriscv/machine_vmcall.hpp#L18
Structs will be pushed onto the stack and the address will take up an integer register slot. So, I can turn a regular function call into a call into my virtual machine. I don't think any other programming language can do that.
Now, for the other way around there are system call handlers. They look like this:
https://github.com/fwsGonzo/libriscv/blob/master/emulator/src/syscalls.cpp#L20
In an effort to simplify system call handling I want to be able to take a list of argument types, perform some logic on each of them (extract the values based on type), and then optionally call a lambda with the arguments I built up.
The number and types of arguments is known beforehand. The values are not known until they are extracted from the machine registers.
Thanks to #bipll for answering. I chose to implement it like this:
template<typename... Args, std::size_t... indices>
inline auto resolve_args(machine_t& m, std::index_sequence<indices...>)
{
std::tuple<std::decay_t<Args>...> retval;
((std::get<indices>(retval) = m.template sysarg<Args>(indices)), ...);
return retval;
}
template<typename... Args>
inline auto resolve_args(machine_t& m) {
return resolve_args<Args...>(m, std::index_sequence_for<Args...>{});
}
Hmm, is this something you're after?
#include <iostream>
#include <type_traits>
template<class... Args> void omg(Args &&...args)
{
((std::is_integral_v<Args> && std::cout << args << " is integral\n"), ...);
}
int main() {
omg(1, 42, 3.14, "Hi!", 0<<0);
}
1 is integral
42 is integral
0 is integral
operator, could be the Swiss army knife of unary foreach fold-expressions.
You don't even need actual values for that:
template<class... Args> void omg()
{
std::size_t i{};
((++i,
std::is_integral_v<Args> && std::cout <<
"Arg #" << i << " is integral\n"
|| std::is_scalar_v<Args> && std::cout <<
"Arg #" << i << " is not integral, yet is scalar\n"
), ...);
}
int main() {
omg<int, int, double, char const *, std::size_t>();
}
If you don't have actual values at hand, but their types and index access, well, you can easily retrieve them through some very basic way:
template<class... Args, std::size_t... indices> void add_args(
std::index_sequence<indices...>)
{
(p.append(sys.get_arg<Args>(indices)), ...);
}
template<class... Args> void add_args() {
add_args<Args...>(std::index_sequence_for<Args...>{});
}
Even storing them in a tuple is a bit tricky and not quite straightforward:
std::tuple<std::decay_t<Args>...> retval;
((std::get<indices>(retval) = sys.get_arg<Args>(indices)), ...);
return retval;

Experimental dispatching with std::apply

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

How to bind variadic template params to function

I'm trying to mimic std::thread constructor functionality:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
I've tried stepping with debugger to see how it works but I couldn't figure it out.
How can I create and store bind type like thread's constructor does ?
Something like this (the syntax maybe wrong):
class myClass{
private:
auto bindType;
public:
template< class Function, class... Args >
explicit myClass( Function&& f, Args&&... args ) : bindType(somehowBind(f, args) {}
void evaluate() {bindType();}
};
Example of usage:
int test(int i) {return i;}
int main(){
myClass my(test, 5);
my.evaluate();
}
Note that I don't care if somehowBind function will ignore the return type i.e. its return type can be something like std::function.
All I wan't to do is understand how I can bind class... Args to a given function f such that after calling somehowBind it will act like std::bind does.
To clarify my point you can think about what I'm trying to achieve as follow:
thread t(test, 5); // unlike the usual std:::thread, this one is created in suspended mode therefore I need somehow to bind `f` with `5` and store it
t.start(); // now t is executed
It's kinda reminds C# and Java threads, they not executed right after construction.
For starters, to bind some parameters to a function using std::bind you simpy do:
// Some function.
void printValues(int x, double y) {
std::cout << x << " " << y << std::endl;
}
auto func = std::bind(printValues, 5, 2.0); // Bind params and return functor.
func(); // Evaluate function call (returns void in this case).
Next, to store a functor and its parameters in a class and you don't care about the return value when evaluating then simply use a lambda expression to wrap the std::bind expression (the lambda is used to drop the return value):
struct Foo {
template <typename Function, typename... Args>
Foo(Function&& func, Args&&... args) {
auto f = std::bind(std::forward<Function>(func), std::forward<Args>(args)...);
func_ = [f] { f(); };
// func_ = [f{std::move(f)}] { f(); }; // In C++14 you can move capture.
}
void evaluate() { func_(); }
std::function<void()> func_;
};
Also see this live example
If you're looking to store a variadic pack then see this answer: How to store variadic template arguments?

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.