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.