我有以下代码。LockWrap
是我想添加到std::map
中的内容。LockWrap
继承了一个noncopyable
,它完全来自boost库。我不能修改LockWrap
的定义。
#include <mutex>
#include <map>
struct base_token {};
class noncopyable: base_token
{
protected:
constexpr noncopyable() = default;
~noncopyable() = default;
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
};
class LockWrap : private noncopyable
{
public:
explicit LockWrap(std::mutex & mut)
: lock_(mut)
{}
std::lock_guard<std::mutex> lock_;
};
LockWrap genLockWrap(std::mutex & mut) {
return LockWrap(mut);
}
int main() {
std::mutex mut;
typedef std::map<int, LockWrap> map_type;
map_type locks_held;
int id = 1;
// None of the following can help.
// locks_held.emplace(std::move(1), genLockWrap(mut));
// locks_held.insert(map_type::value_type{std::move(1), genLockWrap(mut)});
// locks_held.insert(std::move(map_type::value_type{std::move(1), genLockWrap(mut)}));
}
我想要的是将LockWrap对象添加到locks_held
中。然而,我的尝试都不起作用。std::map<>::insert using non-copyable objects and uniform initialization的方式也不起作用。我想这是因为我没有移动构造函数。
我知道我可以在多个互斥体上创建一个统一的锁来解决我的问题。不过,我还是想知道如何解决这个问题。
3条答案
按热度按时间avwztpqn1#
尝试失败的原因是,LockWrap类不仅不可复制,而且由于lock_guard成员而不可移动。因此,使用需要移动构造器将其移动到Map中的creator-function将不起作用。
这样,您既不能复制对象,也不能将对象移动到贴图中,而remaming选项是直接在贴图中就地创建对象。
try_emplace
是你的朋友:try_emplace
就地创建对象,因此不涉及复制。只需传递构造函数所需的参数即可。wqnecbli2#
这是你使用最有用的类型来构造不可移动类型的地方:
然后你只需用途:
这将在转换时构造该对的
LockWrap
成员,因此不需要移动它。frebpwbc3#
你基本上有两个选择:
LockWrap
(通过将互斥体传递给locks_held.emplace()
,例如:godbolt
std::unique_lock
而不是std::lock_guard
,使noncopyable
和LockWrap
类型可移动:godbolt
注意,当您想要锁定多个互斥锁时,
std::scoped_lock
可能是更好的解决方案,因为它内置了死锁预防。