Dean Lee
Dean Lee

Reputation: 127

Is it possible to change the member function pointer from std::bind to lambda?

I coded callback method with std::function, std::bind.

std::function object func1 in class A point to function bFoo(int, int) which is member of class B.

My callback code in my program:

// Class A - A.h
class A
{
  public:
    template<class T>
    void setCallback(T *pClass, void(T::*pFunc)(int, int));

  private:
    std::function<void(int, int)> func1;
}

template<class T>
inline void A::setCallback(T *pClass, void(T::*pFunc)(int, int))
{
  func1 = std::bind(pFunc, pClass, std::placeholders::_1, std::placeholders::_2); 
}

// Class A - A.cpp
...
func1(x,y);
...

// Class B - B.h
class B
{
  public:
    void bFoo(int x, int y);

  private:
    A a; // instance of class A
}

// Class B - B.cpp
B::B()
{
  a.setCallback(this, &B::bFoo);
}

It works fine.

However, I heard that in C++ 14 and higher, std::bind can be completely replaced by lambda, and lambda has many advantages over std::bind.

So I tried to change the bind to lambda and looked up many examples, but in my case I haven't found how to replace bind to lambda.

I want to assign a member function from another class into std::function using lambda, not std::bind.

is this possible?

Upvotes: 0

Views: 388

Answers (2)

bipll
bipll

Reputation: 11940

In brief,

struct A {
    using Callback = std::function<void(int, int)>;
    void setCallback(Callback cb) { func1 = std::move(cb); }
};
B::B() { a.SetCallback([this](int x, int y) { bFoo(x, y); }); }

You should capture this to bind a method to an object.

There should be nothing wrong with std::bind, unless you work for one well-known company that has its own peculiar notion of having its own peculiar notions.

Upvotes: 2

super
super

Reputation: 12928

It would be possible to do it with your current code by using

func1 = [=](int x, int y){ (pClass->*pFunc)(x,y); };

In my opinion it's probably better to write out the lambda at the calling site instead. To do that you need to modify setCallback.

class A
{
  public:
    template<class T>
    void setCallback(T callback);

  private:
    std::function<void(int, int)> func1;
}

template<class T>
inline void A::setCallback(T callback)
{
  func1 = callback; 
}

Then we can call from Bs constructor with a lambda.

class B
{
  public:
    void bFoo(int x, int y);

  private:
    A a; // instance of class A
}

// Class B - B.cpp
B::B()
{
  a.setCallback([&](int x, int y){ bFoo(x, y); }); // & will capture this
}

Upvotes: 2

Related Questions