Can an expired weak_ptr be distinguished from an uninitialized one?

2k views Asked by At

For example:

std::weak_ptr<int> wp1(std::make_shared<int>());
std::weak_ptr<int> wp2;

assert(PointsToValidOrExpiredObject(wp1));
assert(!PointsToValidOrExpiredObject(wp2));

Is such a function possible?

Use case: A class's constructor takes std::weak_ptr<Foo> as a dependency. Passing an expired object is ok (might happen in certain workflows), but passing null means the programmer forget something. I'd like to test for this as part of the constructor's parameter validation.

1

There are 1 answers

2
Casey On BEST ANSWER

std::weak_ptr::owner_before can distinguish between weak pointers that are empty and expired. You can therefore implement PointsToValidOrExpiredObject as:

template <typename T>
bool PointsToValidOrExpiredObject(const std::weak_ptr<T>& w) {
    return w.owner_before(std::weak_ptr<T>{}) ||
           std::weak_ptr<T>{}.owner_before(w);
}

Demo.

Regarding the original uncertainty I had about an expired weak_ptr still maintaining ownership: I'm now certain that the general library-wide thread-safety requirements mandate that an expired weak_ptr continues to have the same ownership. Otherwise, destroying the last remaining shared_ptr in thread A would have to observably modify the state of one/some/all weak_ptrs that share ownership with the shared_ptr in question. If thread B was simultaneously examining the state of such a weak_ptr then you would have a data race introduced by the library implementation which is forbidden in general.