Handover function as parameter that has parameters - c++

I want to pass a callback function that has a parameter:
class foo1{
foo1(void (*callback)(float));
};
foo1::foo1(void (*callback)(float)){
//excecute the callback at some point
}
float foo2(){
return 1.1;
}
void foo3(float f){
//do stuff with f
return;
}
int main(){
void (*p3)(float);
//p3 is a pointer to a function that returns void and has a single float as input
p3 = &foo3(foo2());
//p3 now points to foo3 wich fits the requirements. But it does not make sence to give that pointer an argument.
foo1(p3);
return 0;
}
There are several errors and
I understand that this does not make sence. (See comments in the code) But I don't know how to do it corretly. I want to pass a function as callback that has the input value of foo2.

You can do something more like this instead:
class foo1 {
foo1(void (*callback)(float));
};
float foo2();
foo1::foo1(void (*callback)(float)) {
//excecute the callback at some point
callback(foo2());
}
float foo2() {
return 1.1;
}
void foo3(float f) {
//do stuff with f
}
int main() {
void (*p3)(float);
p3 = &foo3;
foo1(p3);
// or simply:
// foo1(&foo3);
return 0;
}
If you do not want foo1() passing a parameter value to the callback, then don't declare the callback with an input parameter to begin with, use another callback function that calls the intended callback function:
class foo1 {
foo1(void (*callback)());
};
foo1::foo1(void (*callback)()) {
//excecute the callback at some point
callback();
}
float foo2() {
return 1.1;
}
void foo3(float f) {
//do stuff with f
}
void foo4() {
foo3(foo2());
}
int main() {
void (*p4)();
p4 = &foo4;
foo1(p4);
// or simply:
// foo1(&foo4);
return 0;
}
Or, in C++11 and later, you can use a lambda:
class foo1 {
template<class T>
foo1(T callback) {
//excecute the callback at some point
callback();
}
};
Or:
#include <functional>
class foo1 {
foo1(std::function<void()> callback) {
//excecute the callback at some point
callback();
}
};
float foo2() {
return 1.1;
}
void foo3(float f) {
//do stuff with f
}
int main() {
foo1([](){ foo3(foo2()); });
return 0;
}
Or, you can use std::bind():
class foo1 {
template <typename T>
foo1(T callback) {
//excecute the callback at some point
callback();
}
};
or:
#include <functional>
class foo1 {
foo1(std::function<void()> callback) {
//excecute the callback at some point
callback();
}
};
#include <functional>
float foo2() {
return 1.1;
}
void foo3(float f) {
//do stuff with f
}
int main() {
foo1(std::bind(foo3, foo2()));
return 0;
}

You can use a lambda to do that.
Something along this way should work:
struct foo1{
template<typename F>
foo1(F f) {
//excecute the callback at some point
f();
}
};
float foo2(){
return 1.1;
}
void foo3(float){
//do stuff with f
return;
}
int main(){
foo1([param{foo2()}](){ foo3(param); });
}
Consider this expression:
[param{foo2()}](){ foo3(param); }
It creates a callable object having type void(void), that is what you expected by applying the result of the execution of foo2 at the first argument of foo3 (right?).
That's why you can simply invoke it as f() within the constructor of foo1.

Related

How to pass function of one class as argument of another function of another class

I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor().
Here is my program. I think my main() has some mistake.
#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
void (*successor)()=NULL;
void addSuccessor ( void (*f)() )
{
successor=f;
}
void start()
{
cout<<"In Class"<<endl;
if(!successor==NULL)
successor();
else
cout<<"No Successor"<<endl;
}
};
class Second{
public:
void foo()
{
cout<<"Successor";
}
};
int main()
{
Base obj;
Second obj2;
obj.addSuccessor(&obj2.foo());
obj.start();
}
Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)
class Base {
std::function<void()> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
successor();
} else {
std::cout << "No Successor\n";
}
}
};
Then, you can pass a lambda expression to add_successor:
obj.add_successor([&]{ obj2.foo(); });
(live demo)
As a complement to the discussion above (based on #L.F.'s answer):
#include <functional>
#include <iostream>
#include <utility>
class Base {
std::function<int(int)> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
auto z = std::invoke(successor, 100);
std::cout << "Output = " << z << "\n";
} else {
std::cout << "No Successor\n";
}
}
};
class Second {
public:
int foo(int x)
{
auto y = x + x;
std::cout << "Successor\n";
return y;
}
};
int main()
{
Base obj;
Second obj2;
obj.add_successor([&](int x)->int { return obj2.foo(x); });
obj.start();
}

Auto return type matching void

Is this code legal? It compiles but I'm wondering what happens with the return value. Undefined behavior?
class Foo {
public:
void test1() {
}
auto test() -> decltype(test1()) {
return test1(); //<---return void here!
}
};
The code is legal. auto deduces to void and a void function can return another void function. A void function can even
return static_cast<void>("I'm a void");
It's legal, but you can't, for example, assign the result to a variable. [1]
class Foo {
public:
void test1() {
}
auto test() -> decltype(test1()) {
return test1(); //<---return void here!
}
};
int main() {
Foo foo;
auto x = foo.test(); //<---compile error here
}
[1] https://godbolt.org/z/YGAtdJ

C++ using passed function

I have two functions one of them takes a function as an argument this works just fine, but I want to call this passed function in my second one.
class XY {
public:
void first(void f());
void second();
};
void XY::first(void f()){
}
void XY::second(){
f(); //passed function from first()
}
You might use std::function to store the callable and call it later.
class X {
public:
void set(std::function<void()> f) {
callable = f;
}
void call() const {
callable();
}
private:
std::function<void()> callable;
};
void f() {
std::cout << "Meow" << std::endl;
}
Then create X instance and set the callable:
X x;
x.set(f);
Later call the stored callable:
x.call();

function pointer to a templated class method

I am trying to achieve the following code pattern.
struct Worker {
void update(/* function pointer */) {
for(unsigned int i = 0; i < 10; i++) {
/* function execution */
}
}
}
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(/*fptr of Derived1::method2*/);
}
}
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
}
I would like to call Derived1's method2 in the instance of Worker::update. How can I define a function pointer that I can inject into the update function.
struct Worker {
void update(/* function pointer */) {
.....
Make Worker::update a template member-function:
struct Worker {
template<typename Func>
void update(Func&& func) {
.....
or use std::function:
struct Worker {
void update(std::function<void()> func) {
.....
Then pass the callback via a lambda in your BaseCrtp<>::method2 as below:
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
Full example:
#include <iostream>
#include <functional>
struct Worker {
template<typename Func>
void update(Func&& func) {
for(unsigned int i = 0; i < 10; i++) {
func();
}
}
//alternatively....
//
//void update(std::function<void()> func) {
// for(unsigned int i = 0; i < 10; i++) {
// func();
// }
//}
};
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
};
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
};
template<typename T>
void process(BaseCrtp<T>& t){
t.method2();
}
int main(){
Derived1 d1;
process(d1);
}
As seen here or here (std::function alternative).
As Martin Bonner suggested I think you could make use of Worker template with type template parameter containing Derived class and non-type template parameter with a pointer to the method you would like to invoke. This can be done as follows:
template <class T, void (T::*)(void)>
struct Worker {
void update(T *t) {
t->method2();
}
};
struct Foo {
void method2() { }
Worker<Foo, &Foo::method2> worker;
};
int main() {
Foo foo;
foo.worker.update(&foo);
}
[online demo]
This when using compiler optimization should most probably be inlined now which is actually the point of using crtp in a first place:
[godbolt]

Boost function and boost bind: Bind the return value?

This is related to this previous question: Using boost::bind with boost::function: retrieve binded variable type.
I can bind a function like this:
in .h:
class MyClass
{
void foo(int a);
void bar();
void execute(char* param);
int _myint;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
myVector.push_back(boost::bind(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
f();
}
But how can I bind a return value ? i.e.:
in .h:
class MyClass
{
double foo(int a);
void bar();
void execute(char* param);
int _myint;
double _mydouble;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
//PROBLEM IS HERE: HOW DO I BIND "_mydouble"
myVector.push_back(boost::bind<double>(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
double returnval;
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
//THIS DOES NOT WORK: cannot convert 'void' to 'double'
// returnval = f();
//MAYBE THIS WOULD IF I COULD BIND...:
// returnval = _mydouble;
}
If what you want is a nullary function that returns void but assigns a value to _myDouble with the result of foo() before doing so, then you cannot do this easily with just Boost.Bind. However, Boost has another library specifically catered to this sort of thing -- Boost.Phoenix:
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/phoenix/phoenix.hpp>
struct MyClass
{
MyClass() : _myVector(), _myInt(), _myDouble() { }
void setMyInt(int i);
void bar();
void execute();
private:
double foo(int const a) { return a * 2.; }
std::vector<boost::function<void()> > _myVector;
int _myInt;
double _myDouble;
};
void MyClass::setMyInt(int const i)
{
_myInt = i;
}
void MyClass::bar()
{
using boost::phoenix::bind;
_myVector.push_back(
bind(&MyClass::_myDouble, this) =
bind(&MyClass::foo, this, bind(&MyClass::_myInt, this))
);
}
void MyClass::execute()
{
if (_myVector.empty())
return;
_myVector.back()();
double const returnval = _myDouble;
std::cout << returnval << '\n';
}
int main()
{
MyClass mc;
mc.bar();
mc.setMyInt(21);
mc.execute(); // prints 42
mc.setMyInt(3);
mc.execute(); // prints 6 (using the same bound function!)
// i.e., bar has still only been called once and
// _myVector still contains only a single element;
// only mc._myInt was modified
}
problem 1: myVector needs to be a class member.
problem 2: myVector is interested in functions that return doubles and take no arguments, which would be boost::function<double()>
then, to bind _mydouble to the parameter of foo, call boost::bind(&MyClass::foo, this, MyClass::_mydouble) which should give you a compilation warning about casting a double to an int for when foo is called.
The closest you can come with Boost.Bind is providing the toreturn as a parameter.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
class Foo {
int myInt;
double myDouble;
public:
Foo() : myInt(3), myDouble(3.141592) { }
void SetToMyInt(double& param)
{
param = myInt;
}
void SetToMyDouble(double& param)
{
param = myDouble;
}
double Execute()
{
double toReturn = 2;
boost::function<void(double&)> f = boost::bind(&Foo::SetToMyDouble, this, _1);
f(toReturn);
return toReturn;
}
};
int main() {
Foo foo;
std::cout << foo.Execute() << std::endl;
return 0;
}