Reputation: 2595
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
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
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
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
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