当我从函数中返回a时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;
};
Run Code Online (Sandbox Code Playgroud)
它可以像:
int main()
{
Lockable<std::vector<int>> lv;
auto [vec, lock] = lv.borrow();
std::cout << vec.size() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是这个.这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;
}
Run Code Online (Sandbox Code Playgroud)
但这会引发可怕的,难以解析的错误.我认为这与std::lock_guard不可移动有关,但对我来说,它看起来就像我的工作代码.为什么第二个版本不起作用?
有些按摩Lockable确实编译:
template <typename T>
class Lockable {
public:
auto borrow() { return std::pair< T&, std::lock_guard<std::mutex>>{object, mutex}; }
auto borrow() const { return std::pair<const T&, std::lock_guard<std::mutex>>{object, mutex}; }
private:
T object;
mutable std::mutex mutex;
};
Run Code Online (Sandbox Code Playgroud)
实例.
我的想法是明确指定std::lock_guard作为模板参数std::pair,但mutex作为相应的构造函数参数提供(实际上,第二个版本不起作用,因为std::lock_guard它不可移动).std::pair::pair在这种情况下将使用过载(3).
(另外,因为它是C++ 17,我建议使用std::scoped_lock而不是std::lock_guard).