Search code examples
c++lambdashared-ptrpass-by-value

Reset boost::shared_ptr captured by value from lambda


In lambdas, since variables captured by value are stored using the const qualifier, what is the proper way of reseting a boost::shared_ptr from the lambda?

class Test {};
auto testPtr(boost::make_shared<Test>());

// Error: shared_ptr captured with const
auto lambda1([testPtr]()
{
    testPtr.reset();
});    

// Ok: but "testPtr" could be out of scope once the lambda is called
auto lambda2([&testPtr]()
{
    testPtr.reset();
});

I guess that maybe this could work:

auto copyOfTestPtr(testPtr);

auto lambda3([&testPtr, copyOfTestPtr]()
{
    // is it guaranteed that the variable referenced by &testPtr 
    // will exist later on?

    testPtr.reset();
});

// this reference is not necessary anymore so decrement shared_ptr counter
// (the lambda still having a copy so the counter won't be zero)
copyOfTestPtr.reset()

The error given by gcc-5.2.0 with the flag -std=c++14 is:

main.cpp: In lambda function:
main.cpp:15:27: error: no matching function for call to 
'std::shared_ptr<main()::Test>::reset() const'

Just looking for a best practice.


Solution

  • In lambdas [...] variables captured by value are stored using the const qualifier [...]

    The missing part in this sentence is "by default".

    This doesn't have to always be the case. If you want to capture variables in lambdas while still being able to modify them within the lambda, you can add the mutable keyword at the end of the parameter list like this:

      class Test {};
      auto testPtr(boost::make_shared<Test>());
    
      auto lambda1([testPtr]() mutable
                   {
                     testPtr.reset();
                   });
    

    That said, I must mention that this seems totally unnecessary in the provided code, because at the end of the scope of your lambda your shared pointer will be destroyed anyway since you captured it by copy and not by reference.