std::defer_lock_t,std::try_to_lock_t,std::adopt_lock_t(3)

NAME
std::defer_lock_t,std::try_to_lock_t,std::adopt_lock_t - std::defer_lock_t,std::try_to_lock_t,std::adopt_lock_t

Synopsis
   Defined in header <mutex>
   struct defer_lock_t { explicit defer_lock_t() = default; };
   struct try_to_lock_t { explicit try_to_lock_t() = default; }; (since C++11)
   struct adopt_lock_t { explicit adopt_lock_t() = default; };
   std::defer_lock_t, std::try_to_lock_t and std::adopt_lock_t are empty class tag
   types used to specify locking strategy for std::lock_guard, std::scoped_lock,
   std::unique_lock, and std::shared_lock.
   Type Effect(s)
   defer_lock_t do not acquire ownership of the mutex
   try_to_lock_t try to acquire ownership of the mutex without blocking
   adopt_lock_t assume the calling thread already has ownership of the mutex

Example
// Run this code
 #include <mutex>
 #include <thread>
 #include <iostream>
 struct bank_account {
     explicit bank_account(int balance) : balance{balance} {}
     int balance;
     std::mutex m;
 };
 void transfer(bank_account &from, bank_account &to, int amount)
 {
     if(&from == &to) return; // avoid deadlock in case of self transfer
     // lock both mutexes without deadlock
     std::lock(from.m, to.m);
     // make sure both already-locked mutexes are unlocked at the end of scope
     std::lock_guard lock1{from.m, std::adopt_lock};
     std::lock_guard lock2{to.m, std::adopt_lock};
 // equivalent approach:
 // std::unique_lock<std::mutex> lock1{from.m, std::defer_lock};
 // std::unique_lock<std::mutex> lock2{to.m, std::defer_lock};
 // std::lock(lock1, lock2);
     from.balance -= amount;
     to.balance += amount;
 }
 int main()
 {
     bank_account my_account{100};
     bank_account your_account{50};
     std::thread t1{transfer, std::ref(my_account), std::ref(your_account), 10};
     std::thread t2{transfer, std::ref(your_account), std::ref(my_account), 5};
     t1.join();
     t2.join();
     std::cout << "my_account.balance = " << my_account.balance << "\n"
                  "your_account.balance = " << your_account.balance << '\n';
 }

Output:
 my_account.balance = 95
 your_account.balance = 55
  Defect reports
   The following behavior-changing defect reports were applied retroactively to
   previously published C++ standards.
      DR Applied to Behavior as published Correct behavior
   LWG 2510 C++11 the default constructors were non-explicit, made explicit
                       which could lead to ambiguity

See also
   defer_lock
   try_to_lock
   adopt_lock tag constants used to specify locking strategy
   (C++11) (constant)
   (C++11)
   (C++11)
   constructor constructs a lock_guard, optionally locking the given mutex
                 (public member function of std::lock_guard<Mutex>)
                 constructs a unique_lock, optionally locking (i.e., taking ownership
   constructor of) the supplied mutex
                 (public member function of std::unique_lock<Mutex>)