waas1919
waas1919

Reputation: 2595

Callback from C function vs from C++ method

I have Foo class with a bar() method. I also have a bar2() function (outside of any class) And a Xpto class where I need to set the constructor with some callback.

class Foo
{
  //...
  public:
     bar()
     {
       //do stuff..
     }
  //...
}

//isolated C function outside class
void bar2()
{
}

class Xpto
{
  //...
  public:
     Xpto(std::function<void()> &callback)
     {
       //do stuff..
     }
  //...
}

int main()
{
   Xpto x1(bar2); // <---- compiles

   Foo myFoo;
   Xpto x2(myFoo.bar); // <--- doesn't compile

   return 0;
}

Why can I create the Xpto object using a callback method from Foo object?

Upvotes: 1

Views: 88

Answers (4)

Alex
Alex

Reputation: 3381

If you want use method you should use a signature for it, as:

class Xpto
{
  //...
  public:
     template <class T>
     Xpto(void (T::* func)())
     {
       //do stuff..
     }

     Xpto(std::function<void()> &callback)
     {
       //do stuff..
     }
  //...
}

This line void (T::* func)() say that you will accept a method that return void and receives no argument from a objetc T as argument.

And use like that:

Xpto x2(&myFoo::bar);

Upvotes: 2

Barry
Barry

Reputation: 302718

Because myFoo.bar, without the ()s, is not actually a legal C++ expression (though such a thing would be perfectly meaningful in, say, python), whereas bar2 is just a pointer to a nullary free function returning void, which would be convertible to std::function<void()>.

The correct way to refer to a member function would be &Foo::bar, and then you additionally would need to provide an instance of Foo. You could do one of:

Xpto x2(std::bind(&Foo::bar, myFoo));
Xpto x2([myFoo]{ myFoo.bar(); });

Note also that typically you don't want to take arguemnts by std::function<Sig>. Prefer to write your constructor as:

template <typename F>
Xpto(F func) {
    // if you really need a std::function, create it here
}

Upvotes: 1

Telokis
Telokis

Reputation: 3389

You are using implicit conversion for Xpto x1(bar2);. It is calling the implicit constructor of std::function<void()> to create one from bar2.

On the second case, you are giving a member function which has not a signature of void(). If instead is void Foo:*() (pointer to member function).

To work, you have to use std::bind like so :

Xpto x2(std::bind(&Foo::bar, myFoo));

Upvotes: 1

ForEveR
ForEveR

Reputation: 55887

Because myFoo.bar has signature not equal to std::function<void()> (since it's member function). You can use std::bind (and look at right syntax of using member function pointer).

Xpto x2(std::bind(&Foo::bar, std::ref(myFoo)));

Upvotes: 3

Related Questions