Template of wrapper for variadic template functions - c++

I am implementing a template for a wrapper, as in :
C++ function call wrapper with function as template argument
Wrap a function pointer in C++ with variadic template
The wrapper taken from the links above is :
template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args&&... args) {
return fn(std::forward<Args>(args)...);
}
#define WRAPPER(FUNC) wrapper<decltype(&FUNC), &FUNC>
Given two functions foo and foo2 :
int foo (int a) {return a};
template <class T>
T foo2(T a)
{
return a;
}
WRAPPER(foo)(4) /*Works*/
WRAPPER(foo2)(4) /*Doesn't work*/
I understand that it is because decltype(&FUNC) cannot be determined unless the template function is given its arguments' types. The thing is that the information is there at compile time, ie. foo2 is called with an int, so is of type int (int) etc. etc. Isn't there some way to express things so that the type of the function is determined with the type of the arguments ?
Simplification
I removed the template call in the code above to isolate the wrapper part and thus have access to both the function and its arguments on the same "level" :
template<class F, typename... Args>
typename std::result_of<F(Args...)>::type wrapper2(F&& fn, Args&&... args)
{
return fn(std::forward<Args>(args)...);
}
wrapper2(foo, 4) /*works*/
wrapper2(foo2, 4) /* the instance of foo2 to create cannot be determined */
The wrapper should ideally be able to create the correct instance of foo2 given the types of the list of arguments.

Related

Getting the function prototype of a lambda

I'm creating a generic C++ EventEmitter. It's based on Node.js EventEmitter:
template <typename ...Args>
int16_t EventEmitter::addListener(uint32_t eventId, std::function<void(Args...)> cb)
{
...
}
template <typename... Args>
void EventEmitter::emit(uint32_t eventId, Args... args)
{
...
}
It's working as expected (I can register listeners with different prototypes). Eg.:
auto handler = [](int n) { ... };
listener.addListener(0, std::function<void(int)>(handler));
But I don't want to bother typing the whole listener prototype to std::function<...> every time I add one (some have more than 5 parameters), then I decided to create a macro:
#define STDFUNC(fn) std::function<decltype(fn)>(fn)
The problem is when I try to use it with lambdas: decltype(handler) is not void(int), it's class lambda []void (int n)->void instead, generating the error:
(Clang 3.7.1) -> error : implicit instantiation of undefined template
'std::_Get_function_impl<(lambda at ...
I'm scratching my head to get the prototype without that lambda qualifiers but I'm stuck. Any help will be appreciated.
Here is a small program that generates a function object for an arbitrary lambda:
#include <functional>
#include <type_traits>
template <typename R, typename... A>
class build_func_type
{
public:
using type = ::std::function<R(A...)>;
};
template <typename R, typename C, typename... A>
typename build_func_type<R, A...>::type mem_func_to_func( R(C::*)(A...) const)
{
return nullptr;
}
template <typename T>
decltype(mem_func_to_func(&T::operator ())) lambda_to_fp(T le)
{
using func_t = decltype(mem_func_to_func(&T::operator ()));
return func_t{le};
}
int test()
{
auto foo = [](int x) -> int { return x * x; };
auto ftype = lambda_to_fp(foo);
return ftype(5);
}
It uses the function mem_func_to_func to auto-deduce the type of the lambda's operator (). It then uses the build_func_type template to build a function type out of the components of the type of the lambda's operator (). I could possibly have used a constructor in build_func_type and relied on C++17 constructor type deduction for this.
Then lambda_to_fp will take a lambda, using mem_func_to_func to create a pointer to the appropriate function type from a pointer to the lambda's operator () member function. Then it creates a ::std::function of the appropriate type, constructing that type from the type of the function pointer. Then it initializes it with the lambda and returns it.

How to extract a selected set of arguments of a variadic function and use them to call another function

I have a variadic function zoo which takes N arguments, where N is known at compile time (it is a template parameter of the class containing the function).
template <int N>
struct B
{
template <typename... Args>
static void zoo(Args... args)
{
static_assert(size of...(args) == N, "");
// do something
}
};
I have another variadic function foo which takes M arguments, where M>N and is known at compile time (it is a template parameter of the class containing the function). I have a static index_array containing the indices of the arguments of foo I want to pass to zoo.
From the body of foo I want to call zoo passing a selected subset of the arguments of foo.
What is the best way to do this? Ideally achieving perfect inlining, i.e. so that everything is compiled into just one instruction with no function pointers indirections?
template<int...I>
struct indices
{
static constexpr int N = sizeof...(I);
};
template <int M, typename...X>
struct A
{
// here I am simplifying, in reality IS will be built at compile time based on X
typedef indices<0,2,3> IS;
template <typename... Args>
static void foo(Args... args)
{
static_assert(size of...(args) == M, "");
// do some magic to achieve the function call described in pseudo-code
// B<IS::N>::zoo(args(IS(0),IS(1),IS(2)))
// ideally this should be perfectly inlined to just have the call above
}
};
Please note the code above is a simplification of my problem, designed for the purpose of illustrating the question.
EDIT:
As asked below, I describe the use case:
I am playing with a template based library to drive micro-controller pins. A micro controller has several ports (accessible as bytes in memory) and each port has up to 8 pins (bits). Class A is a bundle of pins via the template argument X, where every pin is defined as Pin. Class B manipulates all pins on the same port. A::foo is a function to modify some of the pins, with arguments in the same order as the order with which the pins are specified in the X template argument pack. foo needs to group the arguments by ports and dispatch to the B classes which representing individual ports, where all arguments are fused and written to the controller in a single instruction.
You can create a helper to extract the nth_arg like this:
template <int I>
struct ignore
{
template <typename T>
ignore(T&&) // This constructor accepts anything
{
}
};
template <typename T>
struct nth_arg;
template <size_t... DropIndexes>
struct nth_arg<std::integer_sequence<size_t, DropIndexes...>>
{
template <typename Arg, typename... Rest>
static decltype(auto) get(ignore<DropIndexes>..., // ignore args 0...n-1
Arg&& arg,
Rest&&...) // also ignore the rest
{
return std::forward<Arg>(arg); // return nth arg
}
};
And then call
template <int... Is, typename... Args>
static void call_zoo(indices<Is...>, Args&&... args)
{
B<sizeof...(Is)>::zoo(nth_arg<std::make_index_sequence<Is>>::get(
std::forward<Args>(args)...)...);
}
template <int M>
struct A
{
typedef indices<0, 2, 3> IS;
template <typename... Args>
static void foo(Args... args)
{
static_assert(sizeof...(args) == M, "");
call_zoo(IS{}, std::forward<Args>(args)...);
}
};
If you're using C++11, you can easily roll your own integer_sequence.
Pack the arguments into a tuple of references, and then retrieve them with std::get and a pack expansion on the indices.
template<class Tuple, int... Is>
static void magic(Tuple&& args, indices<Is...>){
B<IS::N>::zoo(std::get<Is>(std::forward<Tuple>(args))...);
}
template <typename... Args>
static void foo(Args... args)
{
static_assert(sizeof...(args) == M, "");
magic(std::forward_as_tuple(args...), IS{});
}
(You may want to make foo take forwarding references.)

C++ universal function caller

I'd want to implement a function caller that works just like the thread constructor. For example
std::thread second (bar,0);
will start a thread which calls bar with the single argument 0. I would like to do the same thing, but I do not know how.
For example, given:
void myFunc(int a){
cout << a << endl;
}
I would like:
int main() {
caller(myFunc,12);
}
to call myFunc with the parameter 12.
std::bind will make a callable object from any callable object with an arbitrary set of parameters, just as the thread constructor does. So just wrap that in a function that calls it:
template <typename... Args>
auto caller(Args &&... args) {
return std::bind(std::forward<Args>(args)...)();
}
Note that the auto return type requires C++14 or later. For C++11, you'll have to either return void, or specify the type:
auto caller(Args &&... args)
-> decltype(std::bind(std::forward<Args>(args)...)())
If all you want to do is call an arbitrary function with an arbitrary argument, that's just a template on both types:
template <typename Function, typename Arg>
void call_with_one(Function&& f, Arg&& arg) {
f(std::forward<Arg>(arg));
}
which you can expand to call with any number of args by making it variadic:
template <typename Function, typename... Arg>
void call_with_any(Function f, Arg&&... args) {
f(std::forward<Arg>(args)...);
}
Or really f should be a forwarding reference as well:
template <typename Function, typename... Arg>
void call_with_any(Function&& f, Arg&&... args) {
std::forward<Function>(f)(std::forward<Arg>(args)...);
}
Note that this will only work with functions and objects that implement operator(). If f is a pointer-to-member, this will fail - you will have to instead use std::bind as Mike Seymour suggests.

How to create a variadic template function with `std::function` as a function parameter?

How can I create a variadic template function with std::function as a function parameter that accepts a variadic number of arguments? I tried to reduce the problem to a MWE:
#include <functional>
template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); }
template <class T, class... Args>
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args... args) {
fun(obj, args...);
}
struct Foo {
void bar() {}
};
int main() {
Foo foo;
std::function<void(Foo *)> fun = &Foo::bar;
run(fun, &foo); // works
run<Foo>(&Foo::bar, &foo); // works
run_variadic(fun, &foo); // works
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
}
It seems like the mere presence of the variadic template parameter in run_variadic makes it impossible to directly call it with a member function pointer. clang's error message is as follows:
main.cpp:21:3: error: no matching function for call to 'run_variadic'
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
^~~~~~~~~~~~~~~~~
main.cpp:6:6: note: candidate template ignored: could not match 'function<void (Foo *, type-parameter-0-1...)>' against 'void (Foo::*)()'
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args&&... args) {
^
1 error generated.
Any suggestions on how I can fix run_variadic so that I do not have to go through the extra std::function object?
Background
I have a class hierarchy as
template <class T> class Abstract { ... };
class UnrelatedStuff { ... };
class Derived : public Abstract<UnrelatedStuff> { ... };
There are multiple Derived classes that all have to implement one or more methods to loop over a range of elements. The loop looks something like
#pragma omp parallel for
for (ZFSId i = begin; i != end; ++i) {
callMemFun(i, and, other, args);
}
All loops should be OpenMP-accelerated. I want the accelerator stuff factored out and not repeated in each method of Derived that uses a loop, so that I only have to change one place if e.g. OpenMP would switch to OpenACC.
Thus I am looking for a way to put the loop (and its decoration) in its own function. Moving it to the Abstract base class is not an option either, since the loops are performance-critical and I cannot have an abstract function call in each loop iteration.
You are almost always certainly better off abstracting away the function object:
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
This allows you to do the right thing at call site:
// function object is a lambda that binds to a member function:
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args...*/);
I prefer a lambda to std::function or std::bind but you can also use those if they are already available:
run(std::function<void(Foo *)>{&Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
I provide a full example program below.
You have now edited the question with new information regarding what you are trying to do.
I'm pretty sure that you don't want to do this, since the OpenMP/OpenACC pragmas like parallel for usually require extra annotations for delivering reasonable performance, and they depend on what you are exactly trying to do at call site.
Still, if you really really want to go this route you can write your own for_each algorithm and dispatch according to an ExecutionAgent (see N3874 and N3731). If OpenMP, TBB, OpenACC parallel task are too slow, you can also easily provide overloads based on e.g. an ExecutionPolicy like this:
template<class RandomAccessRange, class Functor,
class ExecutionPolicy = execution::serial_t>
void for_each(RandomAccessRange&& r, Functor&& f,
ExecutionPolicy&& ex = ExecutionPolicy{}) {
detail::for_each_(std::forward<RandomAccessRange>(r),
std::forward<Functor>(f),
std::forward<ExecutionPolicy>(ex));
}
And then you can implement overloads of for_each_ for each execution policy, e.g.:
namespace detail {
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::serial_t) {
boost::for_each(std::forward<RandomAccessRange>(r), std::forward<Functor>(f));
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openmp_t) {
#pragma omp parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openacc_t) {
#pragma acc parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::tbb_t) {
tbb::parallel_for_each(std::begin(std::forward<RandomAccessRange>(r)),
std::end(std::forward<RandomAccessRange>(r)),
std::forward<Functor>(f));
}
} // namespace detail
Note that the ExecutionPolicy is just a tag, i.e.:
namespace execution {
struct serial_t {}; static const constexpr serial_t serial{};
struct openmp_t {}; static const constexpr openmp_t openmp{};
struct openacc_t {}; static const constexpr openacc_t openacc{};
struct tbb_t {}; static const constexpr tbb_t tbb{};
} // namespace execution
This will at least give you an efficient TBB backend even tho the OpenMP/OpenACC performance will be mediocre at best. You can take a look at the parallel implementation of libstdc++ where they use OpenMP. Their for_each algorithm is over 1000 lines of code and uses work-stealing.
Full example program:
#include <functional>
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
struct Foo { void bar() {} };
int main() {
Foo foo;
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args*/);
run(std::function<void(Foo *)>{ &Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
}
To answer your comment on the previous answer, that answer can be adapted to support pointers to member functions in the way that you've asked for. The previous answer already works for all callable objects, but not directly with a pointer to member function because those are not callable with the usual f(args) syntax. The following version uses tag dispatch to distinguish between pointers to member functions and traditional callable objects, applying the call syntax appropriate to each case.
template <class Functor, class... Args>
void run_helper(std::false_type, Functor f, Args&&... args)
{
f(std::forward<Args>(args)...);
}
template <class Functor, class Arg0, class... Args>
void run_helper(std::true_type, Functor f, Arg0&& arg0, Args&&... args)
{
(std::forward<Arg0>(arg0).*f)(std::forward<Args>(args)...);
}
template <class Functor, class... Args>
void run(Functor f, Args&&... args)
{
run_helper(typename std::is_member_pointer<Functor>::type(),
f, std::forward<Args>(args)...);
}
This can be used in all the same ways as the previous answer could, but also supports directly passing in a pointer to member function:
run(&Foo::bar, foo);
It even works with overloaded member functions and member functions which are templates, if you explicitly instantiate the run template to bind to a particular overloaded function or function template instantiation.
Live example: http://ideone.com/vsBS4H

functions as template argument, plus variadic template argument

I'm writing a generalized function wrapper, that can wrap any function into a lua-style call, which has the form
int lua_function( lua_State *L)
And I wish the wrapper function is generated on-the-fly, so I'm thinking of passing the function as a template argument. This is trivial if you know the number (e.g, 2) of arguments:
template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
However, I don't know the number, so I beg for variadic template argument for help
// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
The above won't compile, since variadic argument has to be the last one. So I use two level template, the outer template captures types, the inner template captures the function:
template <typename R, typename... Args>
struct func_type<R(Args...)>
{
// Inner function wrapper take the function pointer as a template argument
template <R F(Args...)>
struct func
{
static int call( lua_State *L )
{
// extract arguments from L
F(/*arguments*/);
return 1;
}
};
};
That works, except that to wrap a function like
double sin(double d) {}
the user has to write
func_type<decltype(sin)>::func<sin>::apply
which is tedious.
The question is: is there any better, user-friendlier way to do it? (I can't use a function template to wrap the whole thing, coz a function parameter can't be used as a template argument.)
Things like std::function and std::result_of use the following technique to do what you want regarding variadic templates:
template<typename Signature>
struct wrapper; // no base template
template<typename Ret, typename... Args>
struct wrapper<Ret(Args...)> {
// instantiated for any function type
};
You could expand the above to add a non-type Ret(&P)(Args...) template parameter (pointers to function work just as well) but you'd still need a decltype at the user level, i.e. wrapper<decltype(sin), sin>::apply. Arguably it would be a legitimate use of the preprocessor if you decide to use a macro to remove the repetition.
template<typename Sig, Sig& S>
struct wrapper;
template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
int
static apply(lua_State*)
{
// pop arguments
// Ret result = P(args...);
// push result & return
return 1;
}
};
// &wrapper<decltype(sin), sin>::apply is your Lua-style wrapper function.
The above compiles with gcc-4.5 at ideone.
Good luck with implementing the apply that (variadically) pops the arguments (leave me a comment if you open a question about that). Have you considered using Luabind?
As #Juraj says in his comment, the function pointer can be a template argument, see the following simple example:
#include <iostream>
#include <boost/typeof/typeof.hpp>
void f(int b, double c, std::string const& g)
{
std::cout << "f(): " << g << std::endl;
}
template <typename F, F* addr>
struct wrapper
{
void operator()()
{
std::string bar("bar");
(*addr)(1, 10., bar);
}
};
int main(void)
{
wrapper<BOOST_TYPEOF(f), &f> w;
w();
return 0;
}
working version: http://www.ideone.com/LP0TO
I'm using BOOST_TYPEOF as normally I always provide examples in the current standard, but it does something similar to decltype. Is this what you were after?