C++ iterate template parameters - c++

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;

Related

C++ need a container to store user defined function

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)...);
}

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 recover the type of a function pointer at runtime

In the code I register one or multiple function pointer in a manager class.
In this class I have a map that maps the argument types of the function to said function. It may look like so: std::map< std::vector<std::type_index> , void*>
template<typename Ret, typename... Args>
void Register(Ret(*function)(Args...)) {
void* v = (void*)function;
// recursively build type vector and add to the map
}
At runtime the code gets calls (from an external script) with an arbitrary number of arguments. These arguments can be read as primitive data types or as custom types that will be specified at compile time.
With every call from the script, I have to find out which function to call, and then call it. The former is easy and already solved (filling a vector with type_index in a loop), but I can't think of a solution for the latter.
My first approach was using variadic templates in recursion with an added template argument for each read type - but this turned out to be impossible since templates are constructed at compile time, and the arbitrary number of arguments is read at runtime.
Without variadic templates however, I don't see any possibility to achieve this. I considered boost::any instead of void*, but I didn't see how that would solve the need to cast back to the original type. I also thought of using std::function but that would be a templated type, so it could not be stored in a map for functions with different arguments.
(If it's unclear what I'm asking, think of LuaBinds possibility to register overloaded functions. I tried to understand how it's implemented there (without variadic templates, pre-C++11), but to no avail.)
Suppose you had the arguments in a vector of some kind, and a known function (fully).
You can call this. Call the function that does this invoke.
Next, work out how to do this for template<class... Args>. Augment invoke.
So you have written:
typedef std::vector<run_time_stuff> run_time_args;
template<class... Args>
void invoke( void(*func)(Args...), run_time_args rta )
at this point. Note that we know the types of the argument. I do not claim the above is easy to write, but I have faith you can figure it out.
Now we wrap things up:
template<class...Args>
std::function<void(run_time_args)> make_invoker(void(*func)(Args...)){
return [func](run_time_args rta){
invoke(func, rta);
};
}
and now instead of void* you store std::function<void(run_time_args)> -- invokers. When you add the function pointers to the mechanism you use make_invoker instead of casting to void*.
Basically, at the point where we have the type info, we store how to use it. Then where we want to use it, we use the stored code!
Writing invoke is another problem. It will probably involve the indexes trick.
Suppose we support two kinds of arguments -- double and int. The arguments at run time are then loaded into a std::vector< boost::variant<double, int> > as our run_time_args.
Next, let us extend the above invoke function to return an error in the case of parameter type mismatch.
enum class invoke_result {
everything_ok,
error_parameter_count_mismatch,
parameter_type_mismatch,
};
typedef boost::variant<int,double> c;
typedef std::vector<run_time_stuff> run_time_args;
template<class... Args>
invoke_result invoke( void(*func)(Args...), run_time_args rta );
now some boilerplate for the indexes trick:
template<unsigned...Is>struct indexes{typedef indexes type;};
template<unsigned Max,unsigned...Is>struct make_indexes:make_indexes<Max-1, Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;
With that, we can write an invoker:
namespace helpers{
template<unsigned...Is, class... Args>
invoke_result invoke( indexes<Is...>, void(*func)(Args...), run_time_args rta ) {
typedef void* pvoid;
if (rta.size() < sizeof...(Is))
return invoke_result::error_parameter_count_mismatch;
pvoid check_array[] = { ((void*)boost::get<Args>( rta[Is] ))... };
for( pvoid p : check_array )
if (!p)
return invoke_result::error_parameter_type_mismatch;
func( (*boost::get<Args>(rts[Is]))... );
}
}
template<class... Args>
invoke_result invoke( void(*func)(Args...), run_time_args rta ) {
return helpers::invoke( make_indexes_t< sizeof...(Args) >{}, func, rta );
}
And that should work when func's args exactly match the ones passed in inside run_time_args.
Note that I was fast and loose with failing to std::move that std::vector around. And that the above doesn't support implicit type conversion. And I didn't compile any of the above code, so it is probably littered with typos.
I was messing around with variadic templates a few weeks ago and came up with a solution that might help you.
DELEGATE.H
template <typename ReturnType, typename ...Args>
class BaseDelegate
{
public:
BaseDelegate()
: m_delegate(nullptr)
{
}
virtual ReturnType Call(Args... args) = 0;
BaseDelegate* m_delegate;
};
template <typename ReturnType = void, typename ...Args>
class Delegate : public BaseDelegate<ReturnType, Args...>
{
public:
template <typename ClassType>
class Callee : public BaseDelegate
{
public:
typedef ReturnType (ClassType::*FncPtr)(Args...);
public:
Callee(ClassType* type, FncPtr function)
: m_type(type)
, m_function(function)
{
}
~Callee()
{
}
ReturnType Call(Args... args)
{
return (m_type->*m_function)(args...);
}
protected:
ClassType* m_type;
FncPtr m_function;
};
public:
template<typename T>
void RegisterCallback(T* type, ReturnType (T::*function)(Args...))
{
m_delegate = new Callee<T>(type, function);
}
ReturnType Call(Args... args)
{
return m_delegate->Call(args...);
}
};
MAIN.CPP
class Foo
{
public:
int Method(int iVal)
{
return iVal * 2;
}
};
int main(int argc, const char* args)
{
Foo foo;
typedef Delegate<int, int> MyDelegate;
MyDelegate m_delegate;
m_delegate.RegisterCallback(&foo, &Foo::Method);
int retVal = m_delegate.Call(10);
return 0;
}
Not sure if your requirements will allow this, but you could possibly just use std::function and std::bind.
The below solution makes the following assumptions:
You know the functions you want to call and their arguments
The functions can have any signature, and any number of arguments
You want to use type erasure to be able to store these functions and arguments, and call them all at a later point in time
Here is a working example:
#include <iostream>
#include <functional>
#include <list>
// list of all bound functions
std::list<std::function<void()>> funcs;
// add a function and its arguments to the list
template<typename Ret, typename... Args, typename... UArgs>
void Register(Ret(*Func)(Args...), UArgs... args)
{
funcs.push_back(std::bind(Func, args...));
}
// call all the bound functions
void CallAll()
{
for (auto& f : funcs)
f();
}
////////////////////////////
// some example functions
////////////////////////////
void foo(int i, double d)
{
std::cout << __func__ << "(" << i << ", " << d << ")" << std::endl;
}
void bar(int i, double d, char c, std::string s)
{
std::cout << __func__ << "(" << i << ", " << d << ", " << c << ", " << s << ")" << std::endl;
}
int main()
{
Register(&foo, 1, 2);
Register(&bar, 7, 3.14, 'c', "Hello world");
CallAll();
}

How does this variable argument notation work?

In C++ I can define a function with a variable number of arguments like this:
void a(int a...) {
std::cout << a << std::endl;
}
And call it like this:
a(100, 200, 300);
However, apparently I can only access the first argument: The output of the call is 100.
How do I access the other arguments with this notation?
Your syntax is ... unfortunate, and refers to a C-style vararg function.
In C++11 you should prefer variardic templates. The easiest approach is something like this:
First, some helper code:
#include <utility>
template<typename Lambda>
void for_each_arg( Lambda&& unused ) {}
template<typename Lambda, typename Arg1, typename... Args>
void for_each_arg( Lambda&& closure, Arg1&& arg1, Args&&... args ) {
closure( std::forward<Arg1>(arg1) );
for_each_arg( std::forward<Lambda>(closure), std::forward<Args>(args)... );
}
now, we use it:
#include <iostream>
template<typename... Args>
void foo( Args&&... args ) {
for_each_arg( [](int x){
std::cout << x << "\n";
}, std::forward<Args>(args)... );
}
int main() {
foo( 1, 2, 3 );
}
and we can access each argument, and ensure that they convert to int. Note that the conversion to int is deferred until call of the body of for_each_arg.
If you use a var args interface you need to be able to tell from the named parameters how many arguments where provided in total. For example, the <stdio.h> function do that by having the format string be the last named argument followed by as many arguments as specified in the argument list. To access the arguments you need to use the various va_... functions and types.
You are much better off using variadic templates:
template <typename... T>
void f(T... a) {
// just expand the parameter pack over here
}
Sample code using your function a:
#include <iostream>
#include <cstdarg>
void a(int a...)
{
va_list args;
va_start(args, a);
int b = va_arg(args, int);
int c = va_arg(args, int);
std::cout << a << ", " << b << ", " << c << std::endl;
}
int main()
{
a(100, 200, 300);
return 0;
}
The variable argument syntax does not know the number or type of the parameters. Therefore something in the parameter list must indicate the number and possibly the type of the parameters. There are several methods that are typically used to determine the number of parameters:
The first parameter is the number of parameters.
The last parameter is a delimiter, a NULL or other unique value, for example.
The first parameter has other embedded information that determines the number, order and type of the parameters, for example the format parameter for printf.
In this example, I've simply assumed there are three parameters. Calling a with more or less parameters will cause undefined behavior (read, random results, to a crash).
Another variadic solution:
template<typename T, typename... Vs>
void print(T&& t, Vs&&... vs) {
std::cout << std::forward<T>(t) << std::endl;
int sink[] { (std::cout << " " << std::forward<Vs>(vs) << std::endl, 0)... };
(void)sink; // silence "unused variable" warning
}
Which has the benefit of not requiring helpers. We use pack expansion to forward each argument one at a time to cout. For syntax reasons, I leverage the comma operator so that the expression (cout..stuff.., 0) resolves to an integer, which we then discard into an array; this lets us use the pack expansion operator around our complex statement.
A solution which enforces the type int.
But with a usage a little different
#include <initializer_list>
#include <iostream>
// Or you may use std::vector
void print(const std::initializer_list<int>& a) {
for (auto elem : a) {
std::cout << elem << std::endl;
}
}
int main(int argc, char *argv[])
{
print({1, 2, 3}); // extra braces.
return 0;
}

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.