
Howard Hinnant wrote:
But the other constructors / helpers are convenient. Let's review:
// no try-ctor, no try-helper func template <class Lock> void foo1() { Lock lk(m, false); if (lk.try_lock()) ... }
// use a try_lock helper func template <class Lock> void foo2() { if (Lock lk = try_lock(m)) ... }
Notation is a little more compact, but it only works for whatever type Lock that try_lock() returns (presumably scoped_lock).
// use a generic try_lock helper func template <class Lock> void foo3() { if (Lock lk = try_lock<Lock>(m)) ... }
This is now generalized to work for all Lock types.
// use a try-lock ctor template <class Lock> void foo4() { if (Lock lk = Lock(m, try_lock)) ... }
This also works for all Lock types.
The main reason I'm unconvinced about these "useful helper" constructors is that all of the use cases I see on the list are totally bogus. The only real use case for a try_lock (lock_both) does not need helper constructors. The only other real use case templated on a lock (cv::wait) accepts a lock variable and does not need helper constructors. I may be missing something, of course, but the conservative approach is to resist the temptation to provide the "but someone might find them useful!!~1" parts until we see how well they compare to the "no frills" approach in real code.