Automatically Made Weak

I’ve been experimenting with the new “auto everything” style in C++. I also make regular use of std::weak_ptr, often when passing a lambda to be evaluated in another thread where the weak_ptr acts as a monitor to tell if I still need to do what I wanted to do by the time the other thread gets aground to doing it. Usually what happens is that I've already got a shared_ptr to some object and need a weak_ptr to capture in the lambda. This would entail adding the line

 auto weak = std::weak_ptr<SomeType>(shared);

before the line at creates the lambda expression. This isn’t bad, but there is a small cognitive load in there in figuring out what SomeType is. A cognitive load that we can easily offload on the compiler so that instead we can just type

 auto weak = make_weak(shared);

In addition to being easier to type note that by using make_weak we don't have to specify SomeType more than once, which is one less spot we need to make changes if the surrounding code switches to using SomeOtherType in place of SomeType (seems like this should be rare but I end up doing it more than one would expect). Perhaps more importantly, it’s also one less place for a type to be gotten wrong; we can let the computer do the dirty work of keeping the types straight and just get on with our day.

So now you may wondering how you too can jump on the make_weak train. Unlike make_unique, there’s no proposed standardization for make_weak that I know of (had I more time I might write up a proposal myself). Instead, you’ll have to implement it yourself. Luckily the implementation doesn’t require any of the esoterica that make_shared and make_unique require since make_weak can only ever take one argument: the shared_ptr that the weak_ptr is being made for. No need for variadic templates or having to worry about perfect forwarding to get arguments from the call site to the underlying constructor call, just one shared_ptr argument. It runs about five lines:

 template <typename Type_t>
 std::weak_ptr<Type_t> make_weak(const std::shared_ptr<Type_t>& ptr)
    return std::weak_ptr<Type_t>(ptr);

All we’re doing is using the template type-deduction system to do our dirty-work and figure out Type_t for us so we don’t have to spell it out all the time. Plus, it's short enough that the compiler should have no issue inlining any calls so the performance should be identical to directly constructing the weak_ptr. Really it seems like a no-brainer for the standard, especially if “auto-everything” style catches on. maybe I'll have to try and find the time to write up a standardization proposal…

%d bloggers like this: