Is it useful to pass std::weak_ptr to functions?

So is passing std::weak_ptr to functions 100% useless?

No.

Consider this toy example.

struct PointerObserver
{
    std::weak_ptr<int> held_pointer;

    void observe( std::weak_ptr<int> p )
    {
        held_pointer = std::move(p);
    }

    void report() const
    {
        if ( auto sp = held_pointer.lock() )
        {
            std::cout << "Pointer points to " << *sp << "\n";
        }
        else
        {
            std::cout << "Pointer has expired.\n";
        }
    }
};

In this example, a member function observe keeps the data passed to it. This is often called a "sink parameter".

Its weak_ptr parameter communicates that this passed pointer is not owning, but reserves the ability to own at a later time, safely detecting if the pointer has expired.

As a different example, a function that doesn't hold state for later could also usefully receive a weak_ptr parameter in a multithreaded context where the associated data might expire while the function is doing work.


If your clients have a weak_ptr, and your logic could lock it or not, and is valid regardless, then pass a weak_ptr.

As a concrete trivial example:

mutable std::mutex m_mutex;
mutable std::vector<std::weak_ptr<std::function<void(int)>>> m_callbacks;

void clean_callbacks(int x) {
  auto l = std::unique_lock<std::mutex>(m_mutex);
  auto it = std::remove_if( begin(m_callbacks), end(m_callbacks), [](auto w){ return !w.lock(); } );
  m_callbacks.erase( it, end(m_callbacks) );
}
void call_callbacks() {
  clean_callbacks();
  auto tmp = [&]{
    auto l = std::unique_lock<std::mutex>(m_mutex);
    return m_callbacks;
  }();
  for (auto&& wf:tmp) {
    if(auto sf = wf.lock()) {
      (*sf)(x);
    }
  }
}

clean_callbacks has a lambda that takes a weak_ptr. It is used to remove any m_callbacks whose lifetime has ended.

This code is used in a simple broadcaster where broadcasts happen far more often than listeners are invalidated, so waiting for the next broadcast to eliminate a dead listener is a good strategy.