19

In c++0x, there is a std::static_pointer_cast for std::shared_ptr, but there is no equivalent method for std::weak_ptr. Is this intentional, or an oversight? If an oversight, how would I define an appropriate function?

tgoodhart
  • 3,111
  • 26
  • 37

3 Answers3

14

This ought to do it for you:

template<class T, class U>
std::weak_ptr<T>
static_pointer_cast(std::weak_ptr<U> const& r)
{
    return std::static_pointer_cast<T>(std::shared_ptr<U>(r));
}

This will throw an exception if the weak_ptr has expired. If you would rather get a null weak_ptr, then use r.lock() instead.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 1
    Are you aware of the history of this at all? Given how trivial this was to write, I wonder why the standards committee didn't include it. – tgoodhart May 20 '11 at 15:02
  • 2
    I just scanned the standards docs, and it looks to me like no one ever proposed it. I also can't find a record of it being asked for or proposed on boost (the original source of std::weak_ptr). Perhaps the reason is that it is trivial to write, and non-trivial to pick the proper policy (throw or null). And providing two functions (one for each policy) is sub-optimal because `static_pointer_cast` is meant to be a generic name, usable in code where the pointer type is generic. – Howard Hinnant May 20 '11 at 17:30
6

Howard's version is correct, but in many cases it makes sense to simply pass weakptr.lock() as parameter to std::static_pointer_cast:

std::weak_ptr<A> a = ...;  
std::weak_ptr<B> b = std::static_pointer_cast<B>(a.lock());

This syntax explicitly shows what is going on, and makes code easy to read.

Alex
  • 86
  • 1
  • 3
  • 1
    Seems like there's a bug here. Since the a.lock() is a temporary the underlying pointer could be deleted while the code subsequent to this is still using b. -- Actually after reading static_pointer_cast docs again, I'm wrong. It returns a shared pointer that will shares with a's underlying shared pointer. – John Gordon Apr 05 '17 at 17:58
  • This code works, however it involves expensive runtime atomic operations, while static_pointer_cast is always a free operation. – aberaud Jan 10 '23 at 22:25
3

The omission is intentional because despite it's name, std::weak_ptr is not a pointer type and does not provide pointer interface (operator ->, operator *, static_pointer_cast, etc.).

Boris Rasin
  • 448
  • 4
  • 12