绑定到weak_ptr

Sco*_*tty 18 c++ bind callback weak-ptr std-function

有没有办法将std :: bind绑定到std :: weak_ptr?我想存储一个"弱函数"回调,当被调用者被销毁时,它会自动"断开连接".

我知道如何使用shared_ptr创建一个std :: function:

std::function<void()> MyClass::GetCallback()
{
    return std::function<void()>(std::bind(&MyClass::CallbackFunc, shared_from_this()));
}
Run Code Online (Sandbox Code Playgroud)

但是返回的std :: function使我的对象永远保持活着.所以我想将它绑定到weak_ptr:

std::function<void()> MyClass::GetCallback()
{
    std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
    return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
}
Run Code Online (Sandbox Code Playgroud)

但那不编译.(std :: bind将不接受weak_ptr!)有没有办法绑定到weak_ptr?

我已经找到了关于这个的讨论(见下文),但似乎没有标准的实现.存储"弱功能"的最佳解决方案是什么,特别是如果Boost不可用?


讨论/研究(所有这些都使用Boost并且没有标准化):

Nic*_*las 11

std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
Run Code Online (Sandbox Code Playgroud)

你永远不应该这样做.永远.

MyClass::CallbackFunc是类的非静态成员函数MyClass.作为非静态成员函数,必须使用有效的实例调用它MyClass.

整个点weak_ptr是,它并不一定有效.您可以通过将其转换为a来检测其有效性shared_ptr,然后测试指针是否为NULL.由于weak_ptr不保证始终有效,因此无法使用一个非静态成员函数.

你所做的不再有效:

std::bind(&MyClass::CallbackFunc, nullptr)
Run Code Online (Sandbox Code Playgroud)

它可以编译,但当你试图调用它时它最终会崩溃.

最好的办法是使用实​​际逻辑,如果weak_ptr无效则不调用回调函数.bind不是为了做逻辑而设计的; 它只是完全按照你的说法去做:调用函数.所以你需要使用一个合适的lambda:

std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>([thisWeakPtr]()
{
  auto myPtr = thisWeakPtr.lock();
  if(myPtr)
    myPtr->CallbackFunc()
});
Run Code Online (Sandbox Code Playgroud)


Tim*_*ner 2

我能够创建 std::function 的weak_pointers 并使用 clang-3.2 对其进行测试(您没有给出任何编译器限制)。

这是一个示例应用程序,它创建并测试我认为您所要求的内容:

#include <functional>
#include <memory>
#include <iostream>

typedef std::function<void(void)> Func;
typedef std::shared_ptr<Func> SharedFunc;
typedef std::weak_ptr<Func> WeakFunc;


void Execute( Func f ) {
    f();
}


void Execute( SharedFunc sf ) {
    (*sf)();
}


void Execute( WeakFunc wf ) {
    if ( auto f = wf.lock() )
        (*f)();
    else
        std::cout << "Your backing pointer went away, sorry.\n";
}

int main(int, char**) {

    auto f1 = [](){ std::cout << "Func here.\n"; };
    Execute( f1 );

    auto f2 = [](){ std::cout << "SharedFunc here.\n"; };
    SharedFunc sf2( new Func(f2) );
    Execute( sf2 );

    auto f3 = [](){ std::cout << "WeakFunc here.\n"; };
    SharedFunc sf3( new Func(f3) );
    WeakFunc wf3( sf3 );
    Execute( wf3 );

    // Scoped test to make sure that the weak_ptr is really working.
    WeakFunc wf4;
    {
        auto f4 = [](){ std::cout << "You should never see this.\n"; };
        SharedFunc sf4( new Func(f4) );
        wf4 = sf4;
    }
    Execute( wf4 );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

~/projects/stack_overflow> clang++-mp-3.2 --std=c++11 --stdlib=libc++ weak_fun.cpp -o wf && ./wf
Func here.
SharedFunc here.
WeakFunc here.
Your backing pointer went away, sorry.
Run Code Online (Sandbox Code Playgroud)