Хорошо известная проблема с std::lock_guard
(и его родственниками) заключается в том, что он работает не так, как ожидалось, когда создается только временный объект.
Например:
std::mutex mtx;
std::lock_guard<std::mutex> {mtx} // temporary object, does not lock the entire scope
std::lock_guard<std::mutex> lck{mtx} // correct
Я попробовал ссылочные квалификаторы, чтобы создать замену, которая препятствует созданию временного объекта (во время компиляции).Следующий код - тщетная попытка:
#include <mutex>
template<typename T>
struct my_lock {
T &mtx;
my_lock(T &t) : mtx{t} { lock(); }
~my_lock() { unlock(); }
void lock() & { mtx.lock(); };
void unlock() & { mtx.unlock(); };
};
std::mutex mtx;
int main()
{
my_lock<std::mutex> {mtx}; // A
my_lock<std::mutex lck{mtx}; // B
}
Это не работает, поэтому возникает вопрос:
Можно ли написать класс таким образом, чтобы компилятор отклонил A
и принимает B
?