Reputation: 107
I have a function that needs to get std::function-type parameter. I also have an abstract-type pointer to an object. Is it possible to pass the method using only an object?
The function signature:
void foo(std::function<bool(int i)>);
The classes sample:
class IBase // interface
{
public:
virtual bool sampleMethod(int i) = 0;
};
class Child1 : public IBase // one of the classes that inherit from IBase
{
public:
bool sampleMethod(int i) override;
};
So there is this pointer to an object of one of the Child classes:
std::unique_ptr<IBase> ptr;
And I want to use it to pass the sampleMethod as a parameter of foo. Is there any way to do it using std or boost?
Upvotes: 7
Views: 6594
Reputation: 283043
I started writing this based on Paul's answer:
_window.setCursorPosCallback(std::bind(&RenderWorld::mouseCallback, this, std::placeholders::_1,std::placeholders::_2));
But clang-tidy told me to change it to this instead:
_window.setCursorPosCallback([this](auto && x, auto && y) {
mouseCallback(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
});
So that's kinda cool
Upvotes: 3
Reputation: 25388
You can do this with std::bind
and a placeholder:
foo (std::bind (&IBase::sampleMethod, ptr.get (), std::placeholders::_1));
You can also use a lambda which captures ptr
:
foo ([&ptr] (int i) { return ptr->sampleMethod (i); });
In either case, as Yakk - Adam Nevraumont says, make sure that ptr
outlives any references made to it, or copies made of it, in foo
.
Upvotes: 6
Reputation: 275740
This is C++, so you have to worry about lifetime. Your question completely ignores lifetime; that is a bad thing.
Whenever you talk about anything in C++ you must be clear about the lifetime of everything involved. One way to be clear about it is to talk about ownership. Another is to say one thing is to talk about scope.
The lifetime of:
void foo(std::function<bool(int i)> f);
f
and copies of it is not clear. If f
and all copies are not going to live past the exit of foo
, that is completely different than if f
or copies could live past the end of foo
.
Part of this is not your fault; the C++ std
library lacks a vocabulary type to describe "callable object with no state ownership" (a function_ref
), so people use the value-semantics std::function
instead.
Supposing what you really want is a function_ref<void(int)>
, then you can just do this:
foo( [&](int i){ return ptr->sampleMethod(i); } );
and done; the scope guarantees (ptr
outlives the call to foo
, and f
and its copies will not outlive foo
) mean lifetime is accounted for.
If however that foo
may keep a copy of f
, you have two problems. First, ptr
claims unique ownership over the lifetime of *ptr
; but f
also claims ownership over the object it wants to call.
What more, std::function
can be copied; which means either the object it invokes must be copied, or we are forced to have shared ownership.
So after foo
does *ptr
need to available outside? Do copies of *ptr
make sense, or shared ownership between the copies of f
of *ptr
? More ownership questions, and the answers to them change what the right solution to your problem is.
In a more perfect world, function
, moveonly_function
, function_ref
would all exist, and your choice would inform what you need here and simplify the solition.
Upvotes: 2