我正在尝试创建一个非常简单的,简单的C ++类来实现一个线程安全列表,即在您访问它时自动锁定的列表。不幸的是,编译器不希望允许我创建并返回包含Type t = typeof(MyAssembly).Assembly.GetType("MyAssembly.ABC");
var customProperty = t.GetProperty("XYZ"); //check if it is null
的结构。这是我最初尝试过的:
unique_lock
失败
template<typename T>
struct LockedQueue {
private:
std::mutex mutex;
using lock_t = std::unique_lock<std::mutex>;
std::list<T> underlying_list;
public:
struct LockedListAccess {
private:
lock_t lock;
public:
std::list<T> &access;
};
LockedListAccess locked() {
return LockedListAccess{ lock_t{mutex}, underlying_list };
}
};
我猜这意味着大括号初始化程序列表/ C ++ 11统一初始化结构不适用于仅移动类型,如std :: unique_lock。所以我尝试为我的struct创建一个显式构造函数,它将unique_lock作为右值引用,并将其移动到成员中:
no matching function for call to ‘LockedQueue<tcp::socket>::LockedListAccess::LockedListAccess(<brace-enclosed initializer list>)
然而,这也失败了,给我错误
template<typename T>
struct LockedQueue {
private:
std::mutex mutex;
using lock_t = std::unique_lock<std::mutex>;
std::list<T> underlying_list;
public:
struct LockedListAccess {
private:
lock_t lock;
public:
std::list<T> &access;
LockedListAccess(lock_t&& l, std::list<T>& a) :
lock(l), access(a) {};
};
LockedListAccess locked() {
return LockedListAccess{ std::move(lock_t{mutex}), underlying_list };
}
};
这个编译器错误特别令人困惑,因为它指向包含error: use of deleted function ‘std::unique_lock<_Mutex>::unique_lock(const std::unique_lock<_Mutex>&) [with _Mutex = std::mutex]’
的行,我正在尝试使用std :: unique_lock的已删除拷贝构造函数。我将lock(l), access(a)
声明为l
,那么我怎么可能调用复制构造函数呢?
我在互联网上找到的大多数资源似乎表明你可以用std :: move移动unique_locks,虽然似乎没有人通过使用std :: move来解决如何构造包含unique_lock的对象的问题。我在这里做错了什么?
答案 0 :(得分:5)
<强>问题:强>
在LockedListAccess
构造函数的上下文中,lock_t&& l
实际上是一个l值。因此,您需要使用std::move
将其强制转换为r值。一般经验法则:始终std::move
r值引用,始终std::forward
转发引用。
<强>解决方案:强>
LockedListAccess(lock_t&& l, std::list<T>& a)
: lock(std::move(l))
, access(a)
{}
此外,您不需要移动临时锁定对象,因为编译器会自动将临时对象绑定到r值引用。
此:
LockedListAccess locked() {
return LockedListAccess{ std::move(lock_t{mutex}), underlying_list }
}
可以成为:
LockedListAccess locked() {
return LockedListAccess{ lock_t{mutex}, underlying_list }
}