I am trying to make a recursive variadic template function that works in the following example. The example shows no practicality and is only used to help better understand what I'm asking. So, basically I have a function that takes an infinite amount of parameters of the same type and it recursively calls itself with all but the last parameters. Then, once it finally reaches two parameters the next unction serves as the termination of the function. I know the answer isn't trivial and I'm having trouble figuring out exactly what to do. Any help or direction would be appreciated! Thanks.
template <typename... Ts>
void test(int& a, int& b, Ts&... ts){
test(a, b, ... ); //all but the last parameter
//last parameter argument is processed here
}
void test(int& a, int& b){
//end of recursion
}
int main(int argc, char** argv){
int a = 3;
int b = 5;
int c = 6;
int d = 4;
test(a, b, c, d);
return 0;
}
We can forward the arguments in a tuple and decrement the index:
#include <cstddef>
#include <tuple>
#include <utility>
template <std::size_t I, typename Tuple>
void test_helper(Tuple&& tuple)
{
if constexpr (I != 0) {
test_helper<I - 1>(std::forward<Tuple>(tuple));
}
// for example
process(std::get<I>(std::forward<Tuple>(tuple)));
}
template <typename... Args>
void test(Args&&... args)
{
test_helper<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
}
Example:
#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
template <typename T>
void process(const T& arg)
{
std::cout << arg << '\n';
}
template <std::size_t I, typename Tuple>
void test_helper(Tuple&& tuple)
{
process(std::get<I>(std::forward<Tuple>(tuple)));
if constexpr (I != 0) {
test_helper<I - 1>(std::forward<Tuple>(tuple));
}
}
template <typename... Args>
void test(Args&&... args)
{
test_helper<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
}
int main()
{
test(1, '2', "3", 4.0);
}
(live demo)
For now, prefer handling arguments from left to right, which is much simpler:
template <typename... Args>
void test(Args&&... args)
{
((void)process(std::forward<Args>(args)), ...);
}
Handling from right to left will get easier with P1858 Generalized pack declaration and usage, which unfortunately hasn't been adopted yet:
template <typename... Args>
void test(Args&&... args)
{
test(std::forward<Args>(args)...[:-1]...);
if constexpr (sizeof...(Args) != 0) {
process(std::forward<Args>(args)...[-1]);
}
}
Is this the only way to evaluate a parameter pack without using folding (since it requires the use of operators)?
#include <iostream>
template<int ...Is, typename Function>
void eval(Function&& f)
{
// (f(Is)...);
auto op = [&f](int i){f(i); return 0;};
auto doNothing = [](auto...){};
doNothing(op(Is)...);
}
int main()
{
eval<0,1,2>([](int x){std::cout << x << "\n";});
}
Essentially I want to do (f(Is)...), but for some reason, this is disallowed in C++. Is there a more elegant way this can be achieved than by using the workaround presented above?
There is a simpler solution:
#include <iostream>
template<int ...Is, typename Function>
void eval(Function&& f)
{
(f(Is),...);
}
int main()
{
eval<0,1,2>([](int x){std::cout << x << "\n";});
}
I have C code that I want to rewrite in C++. The C code is part of a interpreter where the functions are defined in C however the actual call is from the interpreted source. Basically what it does is listed below:
#include <vector>
void f1(int a0) { }
void f2(int a0,int a1) { }
void f3(int a0,int a1,int a2) { }
void f4(int a0,int a1,int a2,int a3) { }
struct m {
void *p;
int c;
};
std::vector<m> ma;
int addfunc(void *p, int c) {
int i = ma.size();
ma.push_back({p,c});
return i;
}
void call(int idx, int *stack) {
switch (ma[idx].c) {
case 1:
((void (*)(int))ma[idx].p) (stack[0]);
break;
case 2:
((void (*)(int,int))ma[idx].p) (stack[0],stack[1]);
break;
case 3:
((void (*)(int,int,int))ma[idx].p) (stack[0],stack[1],stack[2]);
break;
case 4:
((void (*)(int,int,int,int))ma[idx].p) (stack[0],stack[1],stack[2],stack[3]);
break;
}
}
int main (void) {
int stack[5] = { 0,1,2,3,4 };
/* define */
int i1 = addfunc((void*)f1, 1);
int i2 = addfunc((void*)f2, 2);
int i3 = addfunc((void*)f3, 3);
int i4 = addfunc((void*)f4, 4);
/* call */
call(i1,stack);
call(i2,stack);
call(i3,stack);
call(i4,stack);
}
The addfunc creates a callable object specified by a function pointer and a signature, because the arguments are of the same type int only a count argument for the number of arguments is needed.
When I call a function I specify the function object's index and a stack. The actual c-call is decoded via the argument count and typecasted, the call arguments are taken from the stack.
How can I rewrite the addfunc and call functions as templates objects in C++? How can I use template packs to count the number of arguments for the given function and regenerate the call to the function?
How can I get rid of the switch statement and the function pointer typecast? I have seen that luawrapper's Binder class does something similar. However the code is quite complicated. In my case the arguments are all of the same type.
In the end I want to do something like (pseudocode):
vector<meth> ma;
...
int i0 = addfunc([](int a) { });
int i1 = addfunc([](int a,int b) { });
int i2 = addfunc([](int a,int b,int b) { });
int i3 = addfunc([](int a,int b,int c,int c) { });
...
ma[i0](stack);
ma[i1](stack);
ma[i2](stack);
ma[i3](stack);
Well, if they're just C functions, why not overload on the function pointer type?
std::function<void(std::array<int, 5>)> addfunc(void (*f)(int)) {
return [f](std::array<int, 5> const& a) { f(a[0]); };
}
std::function<void(std::array<int, 5>)> addfunc(void (*f)(int,int)) {
return [f](std::array<int, 5> const& a) { f(a[0], a[1]); };
}
// repeat for all necessary arities
Then create std::vector<std::function<void(std::array<int, 5>)>> and push back all your functions. It's easy, doesn't require any templates and will work reasonably well. It introduces the overhead of std::function, though.
You could get rid of that by introducing your own callable type (n of them), that would correspond to the overloads above, provide an operator() and store appropriate function type inside.
Live example.
Unfortunately, you won't be able to make a completely generic solution, as there is no way to type-erase arity.
One way you can simplify things would be to create a set of wrappers for your functions, each wrapper accepting a stack*, and calling implementation functions with arguments from said stack.
Than you do not need typecasts at all and a simple function pointer (to approriate wrapper) would do (no even need to type-erase).
I propose a C++17 solution (simplified following a Jarod42's observation: thanks) that I suppose is over-complicated.
But I find it funny...
First: a struct that, given (as template parameters) a type and a unsigned number, define a type as the type received.
template <typename T, std::size_t>
struct getType
{ using type = T; };
It's used to convert a variadic template list of numbers in a sequence of types (ints, in the following example) of the same length.
Next: a template type that register (setFunc()) and exec (callFunc()) a function returning void and a sequence of ints length as the first template parameter.
template <std::size_t N, typename = std::make_index_sequence<N>>
struct frHelper;
template <std::size_t N, std::size_t ... Is>
struct frHelper<N, std::index_sequence<Is...>>
{
using fnPnt_t = void(*)(typename getType<int, Is>::type...);
fnPnt_t fp = nullptr;
void setFunc (fnPnt_t fp0)
{ fp = fp0; }
void callFunc (std::array<int, sizeof...(Is)> const & a)
{ if ( fp ) fp(a[Is]...); }
};
Last: a template struct that inherit from a variadic list of preceding structs and enable (using) the setFunc() and the callFunc() members.
template <std::size_t N, typename = std::make_index_sequence<N>>
struct funcRegister;
template <std::size_t N, std::size_t ... Is>
struct funcRegister<N, std::index_sequence<Is...>>
: public frHelper<Is>...
{
using frHelper<Is>::setFunc...;
using frHelper<Is>::callFunc...;
};
Use.
First you have to declare an object of type funcRegister<N> where N is the max number of integer received from your functions plus one. So if you want to use f4(), so four integers, you have to declare
funcRegister<5u> fr;
Then you have to register the functions
fr.setFunc(f1);
fr.setFunc(f2);
fr.setFunc(f3);
fr.setFunc(f4);
and, given some std::array<int, N> of the right size, you can call the registered functions
std::array a1 { 1 };
std::array a2 { 1, 2 };
std::array a3 { 1, 2, 3 };
std::array a4 { 1, 2, 3, 4 };
fr.callFunc(a1); // call f1
fr.callFunc(a2); // call f2
fr.callFunc(a3); // call f3
fr.callFunc(a4); // call f4
The following is a full compiling C++17 example
#include <array>
#include <utility>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
struct getType
{ using type = T; };
template <std::size_t N, typename = std::make_index_sequence<N>>
struct frHelper;
template <std::size_t N, std::size_t ... Is>
struct frHelper<N, std::index_sequence<Is...>>
{
using fnPnt_t = void(*)(typename getType<int, Is>::type...);
fnPnt_t fp = nullptr;
void setFunc (fnPnt_t fp0)
{ fp = fp0; }
void callFunc (std::array<int, sizeof...(Is)> const & a)
{ if ( fp ) fp(a[Is]...); }
};
template <std::size_t N, typename = std::make_index_sequence<N>>
struct funcRegister;
template <std::size_t N, std::size_t ... Is>
struct funcRegister<N, std::index_sequence<Is...>>
: public frHelper<Is>...
{
using frHelper<Is>::setFunc...;
using frHelper<Is>::callFunc...;
};
void f1(int) { std::cout << "f1 called" << std::endl; }
void f2(int,int) { std::cout << "f2 called" << std::endl;}
void f3(int,int,int) { std::cout << "f3 called" << std::endl;}
void f4(int,int,int,int) { std::cout << "f4 called" << std::endl;}
int main()
{
funcRegister<5u> fr;
fr.setFunc(f1);
fr.setFunc(f2);
fr.setFunc(f3);
fr.setFunc(f4);
std::array a1 { 1 };
std::array a2 { 1, 2 };
std::array a3 { 1, 2, 3 };
std::array a4 { 1, 2, 3, 4 };
fr.callFunc(a1);
fr.callFunc(a2);
fr.callFunc(a3);
fr.callFunc(a4);
}
Here is luawrapper's code extracted to be applied the above case. This is more for completion as for #Jerod42's code is preferable.
#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <functional>
#include <vector>
template<typename T> struct tag {};
template<typename TFunctionObject, typename TFirstParamType>
struct Binder {
TFunctionObject function;
TFirstParamType param;
template<typename... TParams>
auto operator()(TParams&&... params)
-> decltype(function(param, std::forward<TParams>(params)...))
{
return function(param, std::forward<TParams>(params)...);
}
};
template<typename TCallback>
static void readIntoFunction(int *stack, TCallback&& callback)
{
callback();
}
template<typename TCallback, typename TFirstType, typename... TTypes>
static void readIntoFunction(int *stack, TCallback&& callback, tag<TFirstType>, tag<TTypes>... othersTags)
{
Binder<TCallback, const TFirstType&> binder{ callback, *stack };
return readIntoFunction(++stack, binder, othersTags...);
}
/* decompose arguments */
template<typename TFunctionType, typename... TOtherParams>
std::function<void(int*)> _addfunc(TFunctionType f, tag<void (*)(TOtherParams...)>) {
return std::function<void(int*)>([f](int *stack) {
readIntoFunction(stack, f, tag<TOtherParams>{}...);
});
}
template<typename TFunctionType>
std::function<void(int*)> addfunc(TFunctionType fn)
{
typedef typename std::decay<TFunctionType>::type RealFuncSig;
return _addfunc(std::move(fn), tag<RealFuncSig>{} );
}
void f1(int a0) { std::cout << a0 << std::endl; }
void f2(int a0, int a1) { std::cout << a0 << a1 << std::endl; }
int main() {
int stack[5] = { 0,1,2,3,4 };
auto a0 = addfunc(&f1);
auto a1 = addfunc(&f2);
a0(stack);
a1(stack);
}
you can use std:function as the parameter of the addfun() and also std::bind
I need something that is the opposite of std::bind, that adds dummy parameters to a function signature instead of how boost::bind binds parameters away.
e.g. I have this function:
std::function<void (void)> myFunc;
But I want to convert it into a std::function<void(int)> to pass into this function
void processFunction( std::function<void(int)> func);
Edit Oh, I mentioned the obvious in chat:
#EthanSteinberg: lambdas?
[] (int realparam, int dummy) { return foo(realparam); }
But it was dismissed, which is why I jump to:
Edit I just realized a much simpler approach: http://ideone.com/pPWZk
#include <iostream>
#include <functional>
using namespace std::placeholders;
int foo(int i)
{
return i*2;
}
int main(int argc, const char *argv[])
{
std::function<int(int, int)> barfunc = std::bind(foo, (_1, _2));
std::cout << barfunc(-999, 21) << std::endl;
// or even (thanks Xeo)
barfunc = std::bind(foo, _2);
std::cout << barfunc(-999, 21) << std::endl;
}
Variadic Templates http://ideone.com/8KIsW
A somewhat longer answer based on variadic templates would result in possibly smaller code at the call site (if you wanted to wrap functions with a long argument list).
#include <iostream>
#include <functional>
int foo(int i)
{
return i*2;
}
template <typename Ax, typename R, typename... A>
struct Wrap
{
typedef R (*F)(A...);
typedef std::function<R(A...)> Ftor;
Wrap(F f) : _f(f) { }
Wrap(const Ftor& f) : _f(f) { }
R operator()(Ax extra, A... a) const
{ return _f(a...); /*just forward*/ }
Ftor _f;
};
template <typename Ax=int, typename R, typename... A>
std::function<R(Ax, A...)> wrap(R (f)(A...))
{
return Wrap<Ax,R,A...>(f);
}
template <typename Ax=int, typename R, typename... A>
std::function<R(Ax, A...)> wrap(std::function<R(A...)> functor)
{
return Wrap<Ax,R,A...>(functor);
}
int main(int argc, const char *argv[])
{
auto bar = wrap(foo);
std::function<int(int, int)> barfunc = wrap(foo);
std::cout << barfunc(-999, 21) << std::endl;
// wrap the barfunc?
auto rewrap = wrap(barfunc);
std::cout << rewrap(-999, -999, 21) << std::endl;
return 0;
}
Generalizing from this would require some more heavy lifting. I think I've seen in the past helpers to 'dissect' (using meta-programming) the signature of a std::function<> and you should be able to make it recognize non-void functions, and perhaps even adding a parameter at the end or in the middle (tricky, as far as I can tell now).
But for your simple case from the OP, it looks like you're covered
You could use a lambda, if your implementation supports it:
processFunction([=](int a){ myFunc(); });
As usual, code first:
#include <functional>
using namespace std;
using namespace std::tr1;
void f(int& r) { r++; }
template<class F, class P> void g1(F f, P t) { f(t); }
template<class F, class P> void g2(F f, P&& t) { f(forward<P>(t)); }
int main()
{
int i = 0;
g1(f, ref(i)); // old way, ugly way
g2(f, i); // new way, elegant way
}
In C++ 98, we don't have a nice way to pefect forward parameters through template functions. So the C++ gurus invented ref and cref to achieve that aim.
Now that we have had r-value reference and perfect forwarding, does it mean that ref and cref and the like should be deprecated?
Reference wrappers are still useful. This is the case when it's about storing things. For example, with reference wrappers you can make std::make_tuple and std::thread create objects which refer to some argument instead of copying them:
class abstract_job
{
public:
virtual ~abstract_job() {}
virtual void run() = 0;
};
class thread
{
public:
template<class Fun, class... Args>
thread(Fun&& f, Args&&... args)
{
typedef typename decay<Fun>::type fun_type;
typedef decltype( make_tuple(forward<Args>(args)...) ) tuple_type;
unique_ptr<abstract_job> ptr (new my_job<fun_type,tuple_type>(
forward<Fun>(fun),
make_tuple(forward<Args>(args)...)
));
// somehow pass pointer 'ptr' to the new thread
// which is supposed to invoke ptr->run();
}
...
};
...
void foo(const int&);
int main()
{
thread t (foo, 42); // 42 is copied and foo is invoked
t.join() // with a reference to this copy
int i = 23;
thread z (foo, std::cref(i)); // foo will get a reference to i
z.join();
}
Keep in mind that
make_tuple(std::ref(i)) // yields a tuple<int&>
make_tuple( i ) // yields a tuple<int>
Cheers!
s
That's assuming reference_wrapper was intended for that. Rather it seems to be mostly about allowing passing function objects by reference where they would be normally taken by value. - If you were to take arguments as T&& instead, wouldn't that mean that passing things by value becomes impossible?
#include <iostream>
#include <functional>
#include <algorithm>
class X: public std::unary_function<int, void>
{
int n;
public:
X(): n(0) {}
void operator()(int m) {n += m;}
int get_n() const { return n; }
};
template <class Iter, class Fun>
void for_each(Iter from, Iter to, Fun&& fun)
{
for (; from != to; ++from)
fun(*from);
}
int main()
{
int a[] = {1, 2, 3};
X x1;
::for_each(a, a + 3, x1);
std::cout << x1.get_n() << '\n'; //6
X x2;
std::for_each(a, a + 3, x2);
std::cout << x2.get_n() << '\n'; //0
X x3;
std::for_each(a, a + 3, std::ref(x3));
std::cout << x3.get_n() << '\n'; //6
}