如何将对象的 class 的方法作为 std::function 传递?
How can I pass a method of an object's class as std::function?
我有一个函数需要获取 std::function 类型的参数。我还有一个指向对象的抽象类型指针。是否可以仅使用对象传递方法?
函数签名:
void foo(std::function<bool(int i)>);
类样本:
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;
};
所以有这个指针指向子类之一的对象:
std::unique_ptr<IBase> ptr;
我想用它来传递 sampleMethod 作为 foo 的参数。
有什么办法可以使用 std 或 boost 来实现吗?
这是C++,所以你不得不担心生命周期。您的问题完全忽略了生命周期;那是一件坏事。
无论何时谈论 C++ 中的任何内容,您都必须清楚所涉及的所有内容的生命周期。弄清楚它的一种方法是谈论所有权。另外就是说一件事就是讲范围。
生命周期:
void foo(std::function<bool(int i)> f);
f
和副本不清楚。如果 f
并且所有副本都不会在 foo
结束后存活,这与 f
或副本可以在 foo
结束后存活完全不同。
部分原因不是你的错; C++ std
库缺少描述 "callable object with no state ownership" (function_ref
) 的词汇类型,因此人们使用值语义 std::function
代替。
假设你真正想要的是function_ref<void(int)>
,那么你可以这样做:
foo( [&](int i){ return ptr->sampleMethod(i); } );
完成;范围保证(ptr
比对 foo
的调用寿命更长,并且 f
及其副本不会比 foo
寿命更长)意味着生命周期被计算在内。
但是,如果 foo
可以保留 f
的副本,那么您会遇到两个问题。首先,ptr
在 *ptr
的生命周期内拥有 唯一的 所有权;但是 f
也声明了它想要调用的对象的所有权。
还有什么,std::function
可以复制;这意味着要么必须复制它调用的对象,要么我们被迫拥有共享所有权。
所以 foo
之后 *ptr
需要在外面可用吗? *ptr
的副本是否有意义,或者 *ptr
的 f
副本之间共享所有权?更多所有权问题及其答案会改变您问题的正确解决方案。
在一个更完美的世界里,function
、moveonly_function
、function_ref
都会存在,你的选择会告知你在这里需要什么,并简化孤独。
您可以使用 std::bind
和一个占位符:
foo (std::bind (&IBase::sampleMethod, ptr.get (), std::placeholders::_1));
您还可以使用捕获 ptr
:
的 lambda
foo ([&ptr] (int i) { return ptr->sampleMethod (i); });
在任何一种情况下,正如 Yakk - Adam Nevraumont 所说,请确保 ptr
在 foo
.
中对它的任何引用或对它的复制都存在。
我根据保罗的回答开始写这篇文章:
_window.setCursorPosCallback(std::bind(&RenderWorld::mouseCallback, this, std::placeholders::_1,std::placeholders::_2));
但是 clang-tidy 告诉我改成这样:
_window.setCursorPosCallback([this](auto && x, auto && y) {
mouseCallback(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
});
太棒了
我有一个函数需要获取 std::function 类型的参数。我还有一个指向对象的抽象类型指针。是否可以仅使用对象传递方法?
函数签名:
void foo(std::function<bool(int i)>);
类样本:
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;
};
所以有这个指针指向子类之一的对象:
std::unique_ptr<IBase> ptr;
我想用它来传递 sampleMethod 作为 foo 的参数。 有什么办法可以使用 std 或 boost 来实现吗?
这是C++,所以你不得不担心生命周期。您的问题完全忽略了生命周期;那是一件坏事。
无论何时谈论 C++ 中的任何内容,您都必须清楚所涉及的所有内容的生命周期。弄清楚它的一种方法是谈论所有权。另外就是说一件事就是讲范围。
生命周期:
void foo(std::function<bool(int i)> f);
f
和副本不清楚。如果 f
并且所有副本都不会在 foo
结束后存活,这与 f
或副本可以在 foo
结束后存活完全不同。
部分原因不是你的错; C++ std
库缺少描述 "callable object with no state ownership" (function_ref
) 的词汇类型,因此人们使用值语义 std::function
代替。
假设你真正想要的是function_ref<void(int)>
,那么你可以这样做:
foo( [&](int i){ return ptr->sampleMethod(i); } );
完成;范围保证(ptr
比对 foo
的调用寿命更长,并且 f
及其副本不会比 foo
寿命更长)意味着生命周期被计算在内。
但是,如果 foo
可以保留 f
的副本,那么您会遇到两个问题。首先,ptr
在 *ptr
的生命周期内拥有 唯一的 所有权;但是 f
也声明了它想要调用的对象的所有权。
还有什么,std::function
可以复制;这意味着要么必须复制它调用的对象,要么我们被迫拥有共享所有权。
所以 foo
之后 *ptr
需要在外面可用吗? *ptr
的副本是否有意义,或者 *ptr
的 f
副本之间共享所有权?更多所有权问题及其答案会改变您问题的正确解决方案。
在一个更完美的世界里,function
、moveonly_function
、function_ref
都会存在,你的选择会告知你在这里需要什么,并简化孤独。
您可以使用 std::bind
和一个占位符:
foo (std::bind (&IBase::sampleMethod, ptr.get (), std::placeholders::_1));
您还可以使用捕获 ptr
:
foo ([&ptr] (int i) { return ptr->sampleMethod (i); });
在任何一种情况下,正如 Yakk - Adam Nevraumont 所说,请确保 ptr
在 foo
.
我根据保罗的回答开始写这篇文章:
_window.setCursorPosCallback(std::bind(&RenderWorld::mouseCallback, this, std::placeholders::_1,std::placeholders::_2));
但是 clang-tidy 告诉我改成这样:
_window.setCursorPosCallback([this](auto && x, auto && y) {
mouseCallback(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
});
太棒了