Using lambda expression as function argument - c++

One of my class member function needs other member functions as arguments. I learnt that the member function pointer or lambda expression can pass the member function to another member function. I did this in my class declaration:
class A
{
public:
void run();
private:
double objfun1();
double objfun2();
.... // and other object function added here
template <typename Callable>
fun_caller(Callable obj_call);
};
When I need to pass different object functions to fun_caller in the public function A::run(), I first define the lambda expression:
void run()
{
... //some code blocks
auto obj_call = [this](){return objfun1();};
fun_caller(obj_call);
... // some code blocks
}
The compiler reports error.
error C2297: '->*': illegal, right operand has type 'Callable'
What's wrong with my lambda expression?
Thank you very much!!

This works:
#include <iostream>
class A
{
public:
void run();
private:
double objfun1(){ return 1.; }
double objfun2(){ return 2.; }
template <typename Callable>
void fun_caller(Callable obj_call){
std::cout << "called: " << obj_call() << "\n";
}
};
void A::run(){
auto obj_call = [this](){return objfun1();};
fun_caller(obj_call);
}
int main(){
A obj;
obj.run();
}

Related

C++ A class member function in a class member function's parameter? [duplicate]

I have written a small program where I am trying to pass a pointer to member function of a class to another function. Can you please help me and where I am going wrong..?
#include<iostream>
using namespace std;
class test{
public:
typedef void (*callback_func_ptr)();
callback_func_ptr cb_func;
void get_pc();
void set_cb_ptr(void * ptr);
void call_cb_func();
};
void test::get_pc(){
cout << "PC" << endl;
}
void test::set_cb_ptr( void *ptr){
cb_func = (test::callback_func_ptr)ptr;
}
void test::call_cb_func(){
cb_func();
}
int main(){
test t1;
t1.set_cb_ptr((void *)(&t1.get_pc));
return 0;
}
I get the following error when I try to compile it.
error C2276: '&' : illegal operation on bound member function expression
You cannot cast a function pointer to void*.
If you want a function pointer to point to a member function you must declare the type as
ReturnType (ClassType::*)(ParameterTypes...)
Further you cannot declare a function pointer to a bound member function, e.g.
func_ptr p = &t1.get_pc // Error
Instead you must get the address like this:
func_ptr p = &test::get_pc // Ok, using class scope.
Finally, when you make a call to a function pointer pointing to a member function, you must call it with an instance of the class that the function is a member of. For instance:
(this->*cb_func)(); // Call function via pointer to current instance.
Here's the full example with all changes applied:
#include <iostream>
class test {
public:
typedef void (test::*callback_func_ptr)();
callback_func_ptr cb_func;
void get_pc();
void set_cb_ptr(callback_func_ptr ptr);
void call_cb_func();
};
void test::get_pc() {
std::cout << "PC" << std::endl;
}
void test::set_cb_ptr(callback_func_ptr ptr) {
cb_func = ptr;
}
void test::call_cb_func() {
(this->*cb_func)();
}
int main() {
test t1;
t1.set_cb_ptr(&test::get_pc);
t1.call_cb_func();
}
In addition to Snps's answer, you could also use a function wrapper from C++11 to store a lambda function:
#include <iostream>
#include <functional>
class test
{
public:
std::function<void ()> Func;
void get_pc();
void call_cb_func();
void set_func(std::function<void ()> func);
};
void test::get_pc()
{
std::cout << "PC" << std::endl;
}
void test::call_cb_func()
{
Func();
}
void test::set_func(std::function<void ()> func)
{
Func = func;
}
int main() {
test t1;
t1.set_func([&](){ t1.get_pc(); });
t1.call_cb_func();
}

using pointer to inline function vs using pointer to function

I want to pass pointers of some functions to a template class to use them later. I was wondering if:
Does it make a possibly (speed-wise) beneficial difference if I make these functions inline?
Functions themselves are possibly one line wrapper for another functions like the example below:
//inline ?
void func_wrapper_1(){
func1(arg1);
}
//inline ?
void func_wrapper_2(){
func2(arg2);
}
and the class template is like the example below:
template<void(*f1)(), void(*f2)()>
class caller{
public:
static void func(int v){
if(v) {
(*f1)();
}else{
(*f2)();
}
}
};
And later on in the main function it will be used like the example below:
caller<func_wrapper_1,func_wrapper_2>::func(0);
caller<func_wrapper_1,func_wrapper_2>::func(1);
I know that every things depends on compiler and compiling option, but lets assume compiler accepts to make these functions inline.
Whether or not a compiler will be smart enough to inline a given situation is up for grabs but I think it may be possible by creating Callable Types by overloading the function call operator.
Something like this:
template<typename Func1, typename Func2>
class caller{
public:
static void func(int v){
if(v) {
// Func1() - creates an object of type Func1
// that object is 'called' using the '()' operator
Func1()();
}else{
Func2()();
}
}
};
struct CallableType1
{
// overloading the function call operator makes objects of
// this type callable
void operator()() const { std::cout << "callable 1" << '\n'; }
};
struct CallableType2
{
void operator()() const { std::cout << "callable 2" << '\n'; }
};
int main()
{
caller<CallableType1, CallableType2> cc;
cc.func(2);
}

How can I pass a member function from a derived class as a callback?

I have a simple class X
class X {
public:
template<typename T>
void doSomething(T &completion) {
std::cout << completion(10) << std::endl;
}
};
and a class A and B
class A {
public:
// some code
X* c;
};
class B : public A {
public:
int test(int x) {
return x * x;
}
void execute() {
auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
c->doSomething(lambda); // works
c->doSomething(&B::test); // does not work
}
};
I want to pass to the doSomething method a member method of class B (or any other class derived from A) but it just does not work :/
How can I pass a member function from a derived class as a callback?
Your problem has nothing to do with B being a child class. Your problem is that you're not binding the non-static member function test() to its instance.
You can address this easily, either by using std::bind to return a functor:
c->doSomething(std::bind(&B::test, this, std::placeholders::_1));
and don't forget to #include <functional>,
or use a lambda to wrap the call by putting this in the lambda captures:
c->doSomething([this](int x){ return this->test(x); });
Note: Make sure to change doSomething()'s parameter to be a rvalue reference so it could properly take all this callback goodness in both temporary objects and otherwise. Should look like this:
template<typename T>
void doSomething(T&& completion)
Make B::test a static method and it will work as written:
static int test(int x) {
return x * x;
}
// ...
c->doSomething(&B::test);
This is because a static method doesn't require an implicit instance (a this pointer).
If B::test must be a regular method, then you must pass the instance by using a capturing lambda, like this:
c->doSomething([this] (int x) { return this->test(x); });
NOTE: when getting this code to compile, I needed to change your definition of doSomething to leave the & off of T:
template<typename T>
void doSomething(T completion) {
std::cout << completion(10) << std::endl;
}
This prevents putting a l-value, or non-const, constraint on the function pointer type, which can prevent the compiler from creating a temporary lambda function.
Do you mean c->doSomething([this](int x) { return this->test(x); }); ?

How to pass a pointer to method as a parameter?

I want to pass a method as an argument to a method which takes an int and returns void:
void A::SetCallback(void (*callback)(int))
{
.....................
}
void B::test()
{
a->SetCallback(&B::Done); //
}
void B::Done(int i)
{
..........................
}
Inside test() I get this error:
Error 1 error C2664: cannot convert parameter 1 from 'void (__thiscall B::* )(int)' to 'void (__cdecl *)(int)'
I saw some example on StackOverflow how to fix this but it uses elements from C++11, to which I do not have access.
How can I fix this using C++03 ?
You cannot pass a non-static method to a function that takes a pointer to a function. Functions and methods are two completely different things. In order to invoke a non-static method you have to, obviously, have an object whose method you're invoking.
If, in your example, Done() is a static class method, then, yes, you can pass it this way, since a static class method is just another name for a function.
It is possible to have a pointer to a class method:
void A::SetCallback(void (B::*callback)(int))
{
}
void B::test()
{
a->SetCallback(&B::Done); //
}
void B::Done(int i)
{
..........................
}
But in order to invoke the class method, you need an object whose method to invoke:
B *object=give_me_a_pointer_to_b_from_somewhere();
(object->*callback)(0);
&ClassName::method_name creates the pointer and void(ClassName::*)(int, char*) is the type.
void go(void(ClassName::*parameter_name)(int, char*));
go(&ClassName::method_name);
You cannot pass a pointer to class method (which is of type void (B::*) (int) in your case) to a pointer to a free function.
What would happen if you could?
void f (void (*g) (int)) {
g(2);
}
struct A {
int x;
void foo (int c) { x += c; }
};
f(&A::foo); // Oh oh! Where will I find `x` in the call `g(2)`?
If you only want pointer to method of B, you need to change the callback type:
void A::SetCallback(void (B::*callback)(int)) { }
But then you need an instance of B to call your callback, e.g.:
B b;
(b.*callback)(2);
I'm using following code. It is not pretty, but you asking for C++03:
#include <iostream>
#include <vector>
#include <functional>
class AbstractCallback {
public:
virtual void call(int arg) = 0;
};
template <class T>
class Callback : public AbstractCallback {
public:
typedef std::mem_fun1_t<void, T, int> CallbackFunc;
private:
CallbackFunc func;
T* object;
public:
Callback(T* _object, const CallbackFunc& _func)
: object(_object), func(_func) {
}
void call(int arg) {
func(object, arg);
}
};
struct A {
void foo(int a) {
std::cout << "foo " << a << std::endl;
}
};
struct B {
void bar(int a) {
std::cout << "bar " << a << std::endl;
}
};
int main() {
A a;
B b;
AbstractCallback* cbs[2] = {
new Callback<A>(&a, std::mem_fun(&A::foo)),
new Callback<B>(&b, std::mem_fun(&B::bar)),
};
cbs[0]->call(10);
cbs[1]->call(22);
delete cbs[0];
delete cbs[1];
return 0;
}
As you can see pointer-to member functions (of type A::* and B::*) are wrapped into std::mem_funs and a Callback class which is generated for each type (A and B in this case).
This allows to keep method of any type in vectors, arrays or lists of abstract callbacks.

Passing a pointer to a class member function as a parameter

I have written a small program where I am trying to pass a pointer to member function of a class to another function. Can you please help me and where I am going wrong..?
#include<iostream>
using namespace std;
class test{
public:
typedef void (*callback_func_ptr)();
callback_func_ptr cb_func;
void get_pc();
void set_cb_ptr(void * ptr);
void call_cb_func();
};
void test::get_pc(){
cout << "PC" << endl;
}
void test::set_cb_ptr( void *ptr){
cb_func = (test::callback_func_ptr)ptr;
}
void test::call_cb_func(){
cb_func();
}
int main(){
test t1;
t1.set_cb_ptr((void *)(&t1.get_pc));
return 0;
}
I get the following error when I try to compile it.
error C2276: '&' : illegal operation on bound member function expression
You cannot cast a function pointer to void*.
If you want a function pointer to point to a member function you must declare the type as
ReturnType (ClassType::*)(ParameterTypes...)
Further you cannot declare a function pointer to a bound member function, e.g.
func_ptr p = &t1.get_pc // Error
Instead you must get the address like this:
func_ptr p = &test::get_pc // Ok, using class scope.
Finally, when you make a call to a function pointer pointing to a member function, you must call it with an instance of the class that the function is a member of. For instance:
(this->*cb_func)(); // Call function via pointer to current instance.
Here's the full example with all changes applied:
#include <iostream>
class test {
public:
typedef void (test::*callback_func_ptr)();
callback_func_ptr cb_func;
void get_pc();
void set_cb_ptr(callback_func_ptr ptr);
void call_cb_func();
};
void test::get_pc() {
std::cout << "PC" << std::endl;
}
void test::set_cb_ptr(callback_func_ptr ptr) {
cb_func = ptr;
}
void test::call_cb_func() {
(this->*cb_func)();
}
int main() {
test t1;
t1.set_cb_ptr(&test::get_pc);
t1.call_cb_func();
}
In addition to Snps's answer, you could also use a function wrapper from C++11 to store a lambda function:
#include <iostream>
#include <functional>
class test
{
public:
std::function<void ()> Func;
void get_pc();
void call_cb_func();
void set_func(std::function<void ()> func);
};
void test::get_pc()
{
std::cout << "PC" << std::endl;
}
void test::call_cb_func()
{
Func();
}
void test::set_func(std::function<void ()> func)
{
Func = func;
}
int main() {
test t1;
t1.set_func([&](){ t1.get_pc(); });
t1.call_cb_func();
}