如何将对象的 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 的副本是否有意义,或者 *ptrf 副本之间共享所有权?更多所有权问题及其答案会改变您问题的正确解决方案。

在一个更完美的世界里,functionmoveonly_functionfunction_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 所说,请确保 ptrfoo.

中对它的任何引用或对它的复制都存在。

Live demo

我根据保罗的回答开始写这篇文章:

_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)); 
});

太棒了