Когда я возвращаю std::lock_guard
в std::pair
из функции, я получаю ужасные ошибки. Но когда я упаковываю его в класс, у меня нет проблем (компилируется и работает как положено). Я не могу понять почему. Подробности следуют:
Я разработал небольшой шаблонный класс для удобной блокировки и разблокировки общих объектов. Он не особенно инновационный, но C ++ 17 позволяет ему быть очень компактным и удобным для чтения / записи:
template <typename T> class Locked {
public:
Locked(T& _object, std::mutex& _mutex)
: object(_object)
, lock(_mutex)
{
}
T& object;
std::lock_guard<std::mutex> lock;
};
template <typename T> class Lockable {
public:
Locked<T> borrow() { return Locked(object, mutex); }
Locked<const T> borrow() const { return Locked(object, mutex); }
private:
T object;
mutable std::mutex mutex;
};
Может использоваться как:
int main()
{
Lockable<std::vector<int>> lv;
auto [vec, lock] = lv.borrow();
std::cout << vec.size() << std::endl;
}
Мой вопрос такой. Класс Locked
очень тонкий. Я думал, что мог бы использовать std::pair
вместо формального класса, вот так:
#include <iostream>
#include <mutex>
#include <utility>
#include <vector>
template <typename T> class Lockable {
public:
std::pair<T&, std::lock_guard<std::mutex>> borrow()
{ return std::pair(object, std::lock_guard<std::mutex>(mutex)); }
std::pair<const T&, std::lock_guard<std::mutex>> borrow() const
{ return std::pair(object, std::lock_guard<std::mutex>(mutex)); }
private:
T object;
mutable std::mutex mutex;
};
int main()
{
Lockable<std::vector<int>> lv;
auto [vec, lock] = lv.borrow();
std::cout << vec.size() << std::endl;
}
Но это выдает ужасные, трудно поддающиеся анализу ошибки. Я думаю, что это связано с тем, что std::lock_guard
не является подвижным, но для меня это выглядит точно так же, как мой рабочий код. Почему эта вторая версия не работает?