Forwarding member function arguments - c++

Thing simple enough, I want to forward the call of a member function, along with its arguments, as described in the following snippet.
Please note that this is not a duplicate of this question, nor this one.
#include <iostream>
#include <functional>
template<class Function, class ... Args>
auto forward_args(Function&& f, Args&& ... args)
{
return f(std::forward<Args>(args)...);
}
int f(int i) { return i; }
struct A {
int get(int i) const { return i; }
};
int main()
{
std::cout << forward_args(f, 2) << std::endl; //ok
A a;
//std::cout << forward_args(&A::get, a, 2) << std::endl; //ko
static auto wrong_wrapper = &A::get;
//std::cout << forward_args(wrong_wrapper, a, 2) << std::endl; //ko again
static std::function<int (const A&, int)> wrapper = &A::get;
std::cout << forward_args(wrapper, a, 2) << std::endl;
}
The commented lines in the main function don't compile (g++ 10.2.0 -- error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘f (...)’, e.g. ‘(... ->* f) (...)’)
I don't quite understand what the compiler is trying to tell me, considering the last cll with the std::function wrapper does work. And, beside fixing the code, I'd also like to know why it doesn't work.

Calling a member function through pointer-to-member still requires this pointer, as in usual (direct) invocations. Simply put, you could succeeded calling A::get() like
static auto wrong_wrapper = &A::get;
(a.*wrong_wrapper)(2);
but what you got after forward_args was instantiated is
A::get(a, 2);
which is not the correct syntax in its nature.
Solution
As it has been already said in the comments section, if you are allowed to use C++17, employ std::invoke. If you aren't, you can work it around using std::reference_wrapper, which accepts any callable type.
template<class Function, class ... Args>
auto forward_args(Function f, Args&& ... args)
{
return std::ref(f)(std::forward<Args>(args)...);
}
I don't forward f here because std::reference_wrapper requires that the object passed is not an rval.
UPD:
Don't forget to specify the trailing return type of forward_args if you use C++11
template<class Function, class ... Args>
auto forward_args(Function f, Args&& ... args) -> decltype(std::ref(f)(std::forward<Args>(args)...))
{
return std::ref(f)(std::forward<Args>(args)...);
}

std::function works because it uses std::invoke which handles calling pointer to member function.
As the solution you could write:
template<class Function, class ... Args>
auto forward_args(Function&& f, Args&& ... args) {
return std::invoke(std::forward<Function>(f), std::forward<Args>(args)...);
}
Syntax for calling member function for an object are:
obj.memberFunction();
obj->memberFunction();
or if you have a pointer to member function:
using Ptr = int (A::*)(int) const;
Ptr p = &A::get;
A a;
(a.*p)(1); // [1]
(obj.*memberFuncPtr)(args...);
the line [1] is valid syntax for calling member function pointed by a pointer. In your case you try A::get(a,2) which is just not valid and cannot work.

Alright, first thing, I still don't understand why forward_args(&A::get, a, 2) doesn't work. Part of the answer was "you need this", but I actually provide it with the second parameter, right ? How is that different from the std::function wrapper ?
On the other hand, while the workarounds proposed in above answer work on the snippet, I actually simplified my original problem too much. I actually need to launch tasks asynchronously, in the following code
thread safety has been removed
yeah, I want to pack all calls in a single data structure, namely tasks, which is wy I start building up wrappers
I don't understand how I can use the proposed solutions to the code below.
#include <iostream>
#include <future>
#include <functional>
#include <queue>
std::queue<std::function<void()>> tasks;
template<class Function, class ... Args>
auto enqueue(Function&& f, Args&& ... args) -> std::future<decltype(f(args...))>
{
std::function<decltype(f(args...))()> func = std::bind(std::forward<Function>(f), std::forward<Args>(args)...);
auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
std::function<void()> wrapper = [task_ptr]() //wrapper to match types of 'tasks'... ugly
{
(*task_ptr)();
};
tasks.push(wrapper);
return task_ptr->get_future();
}
void indep() {}
struct A {
int get(int i) const { return i; }
};
int main()
{
enqueue(indep);
A a;
//enqueue(&A::get, a, 2); //wrong
static auto wrapper_wrong = &A::get;
//enqueue(wrapper_wrong, a, 2); //wrong again
static std::function<int(const A&,int)> wrapper = &A::get;
enqueue(wrapper, a, 2); //ok
static auto autoptr = std::mem_fn(&A::get);
enqueue(autoptr, a, 2); //ok again
}

Related

c++ : variadic template and function overloading

see example below live : https://onlinegdb.com/Hkg6iQ3ZNI
#include <iostream>
#include <utility>
#include <type_traits>
class A
{
public:
A(int v=-10):v_(v){}
void print()
{
std::cout << "called A: " << v_ << std::endl;
}
private:
int v_;
};
void f(int v)
{
std::cout << "called f: " << v << std::endl;
}
template<typename T,typename ... Args>
void run(A&& a,
T&& t,
Args&& ... args)
{
a.print();
t(std::forward<Args>(args)...);
}
template<typename T,typename ... Args>
void run(T&& t,
Args&& ... args)
{
run(A(),
std::forward<T>(t),
std::forward<Args>(args)...);
}
int main()
{
int v_function=1;
int v_a = 2;
run(f,v_function);
return 0;
}
The code above compiles, runs and print (as expected):
called A: -10
called f: 1
but if the main function is modified to:
int main()
{
int v_function=1;
int v_a = 2;
run(f,v_function);
// !! added lines !!
A a(v_a);
run(a,f,v_function);
return 0;
}
then compilation fails with error:
main.cpp:30:6: error: no match for call to ‘(A) (void (&)(int), int&)’
t(std::forward(args)...);
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
which seems to indicate that even when an instance of A is passed as first argument, the overload function
void(*)(T&&,Args&&...)
is called, and not
void(*)(A&&,T&&,Args&&...)
With
template<typename T,typename ... Args>
void run(A&& a,
T&& t,
Args&& ... args)
a is not a forwarding reference, but an rvalue reference. That means when you do run(a,f,v_function); that function will not be selected because a is an lvalue and those can't be bound to rvalue references. There are two quick ways to fix this. First, use std::move on a like
run(std::move(a),f,v_function);
but this isn't great. a isn't actually moved in the function so you are kind of violating the principle of least surprise.
The second option is to make A in the function a template type so it becomes a forwarding reference and then you can constrain it to be of type A like
template<typename A_, typename T,typename ... Args, std::enable_if_t<std::is_same_v<std::decay_t<A_>, A>, bool> = true>
void run(A_&& a,
T&& t,
Args&& ... args)
{
a.print();
t(std::forward<Args>(args)...);
}
Your code works, if you are calling run with an rvalue.
Playable example here.
As NathanOliver already sad: void run(A&& a, T&& t, Args&& ... args) expects an rvalue reference.
Basic idea of an rvalue reference: You are passing an rvalue to a function (e.g. a string literal). That value will be copied to the function. This work is unnecessary. Instead, you are just "moving" the reference to that value, so that it is "owned" by a different part of your program. Move constructors are a good starting point for understanding this problem.

Member function passed as std::function to template, binding all params

I have started building the permission management library,
the basic idea is that you have some sort of configuration read from a file and based on that you can execute a functional object which will be wrapping "allow" and "restrict" functions.
The code so far is divided into few parts
I have a permission manager which says if given "std::string" is able to be executed or not:
class PermissionManager {
public:
virtual bool canAccess(std::string resource) {return true;};
};
Next, I have the actual wrapper on the function:
template <typename FuncT>
class PermissionFunction {
private:
FuncT m_restrict;
FuncT m_allow;
PermissionManager *m_pManager;
std::string m_resource;
public:
PermissionFunction(const PermissionFunction&) = delete;
PermissionFunction& operator=(const PermissionFunction&) = delete;
PermissionFunction(FuncT r, FuncT a, PermissionManager *man, std::string res)
: m_restrict(r), m_allow(a), m_pManager(man), m_resource(res){
}
template<typename ...ARG>
typename std::result_of<FuncT(ARG&&...)>::type operator()(ARG&&... args){
if(m_pManager->canAccess(m_resource)){
return m_allow(std::forward<ARG>(args)...);
} else {
return m_restrict(std::forward<ARG>(args)...);
}
}
};
So, the usage is something like:
PermissionManager tpm{};
std::function<void(int)> testRestrict = [](int a){std::cout << "Restrict" << std::endl;};
std::function<void(int)> testAllow = [](int a){std::cout << "Allow" << std::endl;};
PermissionFunction<decltype(testRestrict)> testPerm(testRestrict, testAllow, &tpm, "hi");
for(int i = 0; i <10; i++){
testPerm(i);
}
It works really nice for the non member std::functions, however when I want to define it with a member function it gets very messy:
class test {
public:
void testato(int i){
std::cout << i << std::endl;
}
PermissionManager perm{};
PermissionFunction<std::function<void(int)>>
permf{
std::bind(&test::testato, this, std::placeholders::_1),
std::bind(&test::testato, this, std::placeholders::_1),
&perm, "hi"};
};
I am wondering if there is any way to shorten up the usage for the member variable types, I was thinking about using the template for that as well but I am not sure how to use std bind with veriadic template parameters and it has to work for any function type.
The goal would be to have the function declaration similar to the one with the std::functions in the example given, so that I can define the member object in this maner:
some_template<decltype(member_f)>
wrapper_member{member_f, member_f, &tpm, "resource"}
Where member_f is an actual member function of a class. Ideally the type would be deduced but I think it would also be acceptable to repeat it in such manner:
some_template<return_t(args_t)>
wrapper_member{member_f, member_f, &tpm, "resource"}
C++20 introduces std::bind_front which binds arguments only to the leading parameters, and so doesn't require the use of placeholder objects. It could be used to make your code more concise.
PermissionFunction<std::function<void(int)>> permf{
std::bind_front(&test::testato, this),
std::bind_front(&test::testato, this),
&perm, "hi"};
A possible C++17 implementation:
#include <tuple>
#include <utility>
template <typename F, typename... Xs>
auto bind_front(F&& f, Xs&&... xs)
{
return [
f = std::forward<F>(f),
xs = std::make_tuple(std::forward<Xs>(xs)...)](auto&&... ys) -> decltype(auto)
{
return std::apply(
f,
std::tuple_cat(xs, std::forward_as_tuple(std::forward<decltype(ys)>(ys)...)));
};
}

Is there in iso or boost function pointer that has the same syntax as std::function

I was wondering if there is a lightweight version of std::function that works only for function pointers but doesnt have horrible :) syntax like regular function pointers.
Aka something like this:
int square(int x)
{
return x*x;
}
//...
function_ptr<int (int)> = square;
Ofc bind and all other fancy stuff std::function supports will fail, but I am ok with that, if I need std::function I will use it.
What you are asking for is for a template to tranform from signature to pointer to function to signature, that is, to add a pointer to the type. That is already done in the standard library:
std::add_pointer<X>::type
But since what you want is the nicer syntax, you can add a template alias:
template <typename T>
using ptr = typename std::add_pointer<T>::type;
Then you can use it directly in your container:
void f(int);
std::vector<ptr<void (int)>> v; // vector of pointers to functions taking `int`
v.push_back(&f);
Depending on the context you want to use this in, it could be as simple as auto and/or decltype:
#include <iostream>
int main()
{
auto f = square;
std::cout << f(5) << std::endl;
// define a type
using F = decltype(&square);
F g = square;
std::cout << g(5) << std::endl;
}
You can write an opaque wrapper if you do not want to use typedef directly. A prototype implementation using variadic templates is as follows. The same technique can be extended to other callable objects such as lambdas.
#include <iostream>
template<typename T>
struct function_ptr {};
template<class R, class... Args>
struct function_ptr<R(Args...)>{
typedef R (*funcType)(Args...);
function_ptr(funcType f) : _f(f) {}
funcType _f;
R operator()(Args... args) { return _f(args...);}
};
int square(int x) {
return x*x;
}
int main() {
function_ptr<int (int)> f = square;
std::cout << f(2) << std::endl;
}

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?

Deducing type for overloaded functions - currying

Given a callable object ( a function ) a, and an argument b ( or a series of arguments ), I would like to deduce the type returned from f considering that f is overloaded with multiple signatures.
one of my many attempts is
#include <iostream>
#include <cstdint>
#include <string>
#include <functional>
#include <utility>
#include <typeinfo>
int foo(uint32_t a) { return ((a + 0) * 2); }
bool foo(std::string a) { return (a.empty()); }
/*template <typename A, typename B> auto bar(A a, B b) -> decltype(a(b)) {
return (a(b));
}*/
/*template <typename A, typename B> decltype(std::declval<a(b)>()) bar(A a, B b)
{
return (a(b));
}*/
template <typename A, typename B> void bar(std::function<A(B)> a, B b) {
std::cout << a(b) << "\n";
}
int main() {
// the following 2 lines are trivial and they are working as expected
std::cout << foo(33) << "\n";
std::cout << typeid(decltype(foo(std::string("nothing")))).name() << "\n";
std::cout << bar(foo, 33) << "\n";
//std::cout << bar(foo, std::string("Heinz")) << "\n";
return (0);
}
and 2 templates options are commented out and included in the previous code.
I'm using declval result_of auto decltype without any luck.
How does the overloading resolution process works at compile time ?
If anyone wants to know why I'm trying to get creative with this, is that I'm trying to implement some Currying in C++11 in a workable/neat way.
The problem is that you can't easily create a function object from an overload set: when you state foo or &foo (the function decays into a function pointer in most case, I think) you don't get an object but you get an overload set. You can tell the compiler which overload you want by either calling it or providing its signature. As far as I can tell, you don't want either.
The only approach I'm aware of is to turn your function into an actual function object which makes the problem go away:
struct foo_object
{
template <typename... Args>
auto operator()(Args&&... args) -> decltype(foo(std::forward<Args>(args)...)) {
return foo(std::forward<Args>(args)...);
}
};
With that wrapper which is unfortunately needed for each name, you can trivially deduce the return type, e.g.:
template <typename Func, typename... Args>
auto bar(Func func, Args&&... args) -> decltype(func(std::forward<Args>(args)...)) {
// do something interesting
return func(std::forward<Args>(args)...);
}
int main() {
bar(foo_object(), 17);
bar(foo_object(), "hello");
}
It doesn't quite solve the problem of dealing with overload sets but it gets reasonably close. I experimented with this idea, essentially also for the purpose of currying in the context of an improved system of standard library algorithms and I'm leaning towards the algorithms actually being function objects rather than functions (this is desirable for various other reasons, too; e.g., you don't need to faff about when you want to customize on algorithm with another one).
If foo is overloaded, you need to use the following:
#include <type_traits>
int foo(int);
float foo(float);
int main() {
static_assert(std::is_same<decltype(foo(std::declval<int>())), int>::value, "Nope.");
static_assert(std::is_same<decltype(foo(std::declval<float>())), float>::value, "Nope2.");
}
If it's not, then this will suffice:
#include <type_traits>
bool bar(int);
int main() {
static_assert(std::is_same<std::result_of<decltype(bar)&(int)>::type, bool>::value, "Nope3.");
}
Yes, it is verbose because you're trying to explicitly extract what implicit ad-hoc overloading does for you.
This is actually already implemented for you std::result_of. Here is a possible implementation
template<class>
struct result_of;
// C++11 implementation, does not satisfy C++14 requirements
template<class F, class... ArgTypes>
struct result_of<F(ArgTypes...)>
{
typedef decltype(
std::declval<F>()(std::declval<ArgTypes>()...)
) type;
};