C++ universal function caller - c++

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.

Related

Restrict function template for member functions only

I am working in C++11 and have the following code that compiles. But the problem is that the function func in the below example can also be called with a std::function, lambda, pointer to a function etc.
Instead, I want that func should only be called by a pointer to a non-static member function of any class. That is, I want to restrict this function only member function pointers.
template <typename Callable, typename... Args> void func(Callable&& callable, Args&&... args)
{
}
struct Test
{
int someMember(int x)
{
return x;
}
};
void g(int, int, int)
{
}
int main()
{
func(g, 1, 1, 1); //this works currently but it should be rejected in the modified program
func([](int){}, 42); //this works currently but it should be rejected in the modified program
Test test;
func(&Test::someMember, test, 1);// this works currently and should work in the modified version
}
As we can see in the above program, all of the calls to func works. But I want that only the call func(&Test::someMember, test, 1); should work and the other two calls should be rejected.
So how can I achieve this. Maybe there is a way to use SFINAE or some other metaprogramming technique.
I think static_assert (with std::is_member_function_pointer) is the perfect tool for the situation. No need to change the signature of func, and the error message can be whatever you want, so it's clearer than, for example, a substitution failure.
To call callable, you may use std::mem_fn.
template <typename Callable, typename... Args>
void func(Callable callable, Args&&... args)
{
static_assert(std::is_member_function_pointer<Callable>::value, "callable must be a member function");
std::mem_fn(callable)(args...);
}
Demo
This can be done by setting up the template parameters in such a way that only pointers to member function are accepted(as shown below). In particular, we can have 4 template parameters corresponding to the class, member function parameters, object of that class and finally the arguments passed to that member function.
template<typename className, typename... Param,typename Ret, typename... Args>
void func(Ret (className::*ptrFunc)(Param... param),className& Object, Args... args)
{
(Object.*ptrFunc)(args...); //std::invoke(ptrFunc, Object, args...) in C++17
}
int main()
{
Test test;
func(&Test::someMember, test, 1);//only this form works now
}
Working demo
Maybe there is a way to use SFINAE or some other metaprogramming technique.
That would do it, since we have std::is_member_function_pointer.
template <typename Callable, typename... Args>
typename std::enable_if<std::is_member_function_pointer<Callable>::value, void>::type
func(Callable callable, Args&&... args)
{
}
If the predicate is false, enable_if produces no type, and our template has no return type, making the function non-viable.
The change to pass by value is because it makes to controlling condition simpler, and because we are only passing pointers to members (fairly cheap to copy).

How to use std::function using variadic template

There is a template for constructing std::function:
template< class R, class... Args >
class function<R(Args...)>;
I have not figured out how to invoke it. (VC++, if that matters.)
Question: How can I use std::function with a variadic list without using std::bind?
#include <functional>
#include <iostream>
using vfunc = std::function<void()>;
using namespace std; // I know, I know.
template<class F, class... Args>
void
run(F&& f, Args&&... args) {
vfunc fn = bind(forward<F>(f), forward<Args>(args)...); //OK
//vfunc fn = vfunc(forward<F>(f), forward<Args>(args)...); // COMPILER ERROR
fn();
}
void foo(int x) {
cout << x << " skidoo\n";
}
int main() {
run(foo, 23);
return 0;
}
There is a template for constructing std::function.
template< class R, class... Args >
class function<R(Args...)>;
That's not what that declaration means. It's not declaring a constructor or a "template for constructing" anything; it's a specialization for the template class std::function. The specialization is the only definition of std::function; the base template is never defined. I think the point of this has something to do with using a function signature in the template declaration. That is, being able to use the template via function rather than as function.
You want to take a callable object and some number of values and create a new callable object that stores those values, which has an operator() overload that calls the given function with those values. std::function does not do that; it has no constructors for doing so.
This is exactly what std::bind is for. Basically, your code is fine as is: storing the result of bind within function is entirely valid.
In that case, you can just wrap the function in a lambda and construct your std::function from it.
template<class F, class... Args>
void run(F&& f, Args&&... args) {
auto fn = vfunc{
[=]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
};
fn(); // fn is of type std::function<void()>
}
I made the lambda mutable so std::forward will not silently not move.
Note however that the [=] capture will copy everything. To support move only types, you can use a tuple:
[f = std::forward<F>(f), args = std::tuple{std::forward<Args>(args)...}]() mutable {
std::apply(std::forward<F>(f), std::move(args));
}
In C++20, this becomes easier:
[f = std::forward<F>(f), ...args = std::forward<Args>(args)...]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

Template of wrapper for variadic template functions

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.

std::enable_if an argument is a function?

Why does the following compile under C++11? (I know it won't link.) I would expect the std::enable_if test to fail since 1() is not a function type.
#include <type_traits>
template <typename Func, typename... Args>
typename std::enable_if<std::is_function<Func(Args...)>::value>::type
delegate(Func, Args...);
int main(void) {
delegate(1); // << Why does this line compile?
return 0;
}
Func is int, Args is empty, so Func(Args...) is int(), i.e., "function of () returning int".
Anything that is_function returns true for can't be the type of a by-value function parameter, so it's not obvious what you want to do.
I was trying to get delegate to only be callable when Func is a
function (preferably function pointer) that can be applied to Args...
Use expression SFINAE for that.
template <typename Func, typename... Args>
auto delegate(Func f, Args... args) -> decltype(f(args...), void());
Depending on what you actually want to do, you may want to std::move f and args.
The code you have written will always yield true. You probably meant std::is_function<Func>...
Though not sure, it seems like you do not need enable_if at all, and you'd better of with a simple
template <class R, class... ARGS>
R delegate2(R (*fun)(ARGS...), ARGS...);
However, if I am wrong and enable_if is a key to success in your case, here is how you can do this:
#include <type_traits>
template <typename Func, typename... Args>
typename std::enable_if<std::is_function<std::remove_pointer_t<Func>>::value>::type
delegate(Func, Args...);
void check(int);
int main(void) {
delegate(check, 10); // << good line compiles
delegate(10); // << this bad line does not
return 0;
}
Based on this comment:
I was trying to get delegate to only be callable when Func is a function (preferably function pointer) that can be applied to Args...
you're using the wrong type trait. To check if Func is callable with Args..., you need to construct an expression that would actually call an instance of Func with those arguments. For that, there's std::result_of_t (in C++14, it becomes SFINAE friendly):
template <typename Func, typename... Args,
class R = std::result_of_t<Func(Args...)>>
R delegate(Func, Args...);
Or, in C++11, just write that out with decltype and declval:
template <typename Func, typename... Args,
class R = std::declval<Func>()(std::declval<Args>()...)>
R delegate(Func, Args...);

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