Brian McFarland Brian McFarland - 4 months ago 16
C++ Question

Is there a shorthand for std::lock_guard<std::mutex> lock(m)?

Exactly what the question states. In C++, ideally 11, but curious about 14 and later too, is there a shorthand syntax for:

std::mutex someMutex;
std::lock_guard<std::mutex> lg(someMutex);


Ideally something that infers the type of mutex to avoid the refactoring if I ever wanted to change to a
std::recursive_mutex
.

In other words, a way to do this:

std::mutex someMutex;
std::lock_guard lg(someMutex);


Or

auto lg = make_lock_guard(someMutex);


For all the type deduction powers of modern C++, it just seems awfully redundant to go typing
std::lock_guard<std::mutex>
every time I want to make one.

Answer

For pre-C++17:

template<class Mutex>
std::lock_guard<Mutex> make_lock_guard(Mutex& mutex) {
    mutex.lock();
    return { mutex, std::adopt_lock };
}

Use as:

std::mutex someMutex;
auto&& lg = make_lock_guard(someMutex);

This takes advantage of the fact that copy-list-initialization doesn't create an additional temporary (even conceptually). The one-parameter constructor is explicit and can't be used for copy-list-initialization, so we lock the mutex first and then use the std::adopt_lock constructor.

The return value is then directly bound to lg, which extends its lifetime to that of the reference, once again creating no temporary (even conceptually) in the process.