kman
kman

Reputation: 107

C++ bind to weak_ptr not working

I have a simple test where I am trying to bind a weak_ptr argument to a global function that takes a weak_ptr, and invokes a method if the backing pointer is still valid.

This seems to work when I create a lambda with the weak pointer. It also works if I call the global method directly, with the weak_ptr. However if I bind the global function to the weak_ptr in advance, it does not seem to work. Following watered down code illustrates the question.

I must be missing something simple. Any clues?

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

using namespace std;

class MyValue : public enable_shared_from_this<MyValue>
{
    public:
        MyValue (int i)
        {
            value = i;
        }

        ~MyValue()
        {
        }

        int getValue() { return value; }

        void printValue() { cout << value << endl; }

    private:

        int value;
};

void callWeakFunction (weak_ptr<MyValue> weakValue)
{
    shared_ptr<MyValue> strongPtr = weakValue.lock();

    if (strongPtr)
    {
        strongPtr->printValue();
    }
    else
    {
        cout << "Sorry, your backing pointer is gone" << endl;
    }
}

int main()
{
    weak_ptr<MyValue> weakValue;

    // Try binding a global function to the weak pointer, doesn't seem to work
    function<void()> weakPrintValue = bind(callWeakFunction, weakValue);

#if 0
    // Create a lambda - this works fine
    function<void()> weakPrintValue ([&weakValue]()
                       {
                           shared_ptr<MyValue> ptr = weakValue.lock();
                           if(ptr)
                           {
                               ptr->printValue();
                           }
                           else
                           {
                               cout << "Sorry, backing pointer is gone" << endl;
                           }
                       });
#endif

    {
        shared_ptr<MyValue> value = make_shared<MyValue>(7);

        weakValue = value;

        // Backing pointer is present
        weakPrintValue();    // This does not work, but callWeakFunction (weakValue) works fine
    }

    // No backing pointer
    weakPrintValue();
}

Resulting output:

Sorry, your backing pointer is gone
Sorry, your backing pointer is gone

Expecting the first weakPrintValue to print the value (7)

Upvotes: 0

Views: 485

Answers (3)

GreenScape
GreenScape

Reputation: 7717

I believe bind() captures weakValue by value. It returns resulting object that has it's own copy of weakValue. When you change local weakValue it does not affect the copy inside of the object returned by bind().

Upvotes: 0

Alan Stokes
Alan Stokes

Reputation: 18964

I wouldn't expect either to work. In both cases you're capturing the initial value of weak_value when it is empty. To be affected by the subsequent assignment to it you need to capture by reference instead. So in the lambda you need [&weak_value], and for the bind you need

bind(callWeakFunction, cref(weakValue));

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249193

I think you want to wrap the weak_ptr in ref() to evaluate it lazily:

function<void()> weakPrintValue = bind(callWeakFunction, ref(weakValue));

Upvotes: 1

Related Questions