Can';t将std::unique\u锁移动到结构中 我试图创建一个非常简单的C++类来实现线程安全列表,即在访问时自动锁定的线程。不幸的是,编译器不允许我创建并返回包含唯一锁的结构。这是我最初尝试的: 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 }; } }; 模板 结构锁定队列{ 私人: std::互斥互斥; 使用lock\u t=std::unique\u lock; std::列表基础_列表; 公众: 结构LockedListAccess{ 私人: 锁(t)锁;; 公众: std::列表和访问; }; LockedListAccess已锁定(){ 返回LockedListAccess{lock\u t{mutex},底层的{u list}; } };

Can';t将std::unique\u锁移动到结构中 我试图创建一个非常简单的C++类来实现线程安全列表,即在访问时自动锁定的线程。不幸的是,编译器不允许我创建并返回包含唯一锁的结构。这是我最初尝试的: 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 }; } }; 模板 结构锁定队列{ 私人: std::互斥互斥; 使用lock\u t=std::unique\u lock; std::列表基础_列表; 公众: 结构LockedListAccess{ 私人: 锁(t)锁;; 公众: std::列表和访问; }; LockedListAccess已锁定(){ 返回LockedListAccess{lock\u t{mutex},底层的{u list}; } };,c++,c++11,locking,move-semantics,C++,C++11,Locking,Move Semantics,这与 no matching function for call to ‘LockedQueue<tcp::socket>::LockedListAccess::LockedListAccess(<brace-enclosed initializer list>) 调用“LockedQueue::LockedListAccess::LockedListAccess()时没有匹配的函数 我猜这意味着大括号初始值设定项列表/C++11结构的统一初始化不适用于仅移动类型,如

这与

no matching function for call to ‘LockedQueue<tcp::socket>::LockedListAccess::LockedListAccess(<brace-enclosed initializer list>)
调用“LockedQueue::LockedListAccess::LockedListAccess()时没有匹配的函数 我猜这意味着大括号初始值设定项列表/C++11结构的统一初始化不适用于仅移动类型,如std::unique\u lock。因此,我尝试为我的结构创建一个显式构造函数,该构造函数将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(lock_t&& l, std::list<T>& a) :
                    lock(l), access(a) {};
        };
        LockedListAccess locked() {
            return LockedListAccess{ std::move(lock_t{mutex}), underlying_list };
        }
};
模板
结构锁定队列{
私人:
std::互斥互斥;
使用lock\u t=std::unique\u lock;
std::列表基础_列表;
公众:
结构LockedListAccess{
私人:
锁(t)锁;;
公众:
std::列表和访问;
锁定列表访问(锁定t&l,标准::列表(&a):
锁(l),通道(a){};
};
LockedListAccess已锁定(){
返回LockedListAccess{std::move(lock{mutex}),底层的{u list};
}
};
然而,这也失败了,给了我一个错误

error: use of deleted function ‘std::unique_lock<_Mutex>::unique_lock(const std::unique_lock<_Mutex>&) [with _Mutex = std::mutex]’
错误:使用删除的函数'std::unique\u lock::unique\u lock(const std::unique\u lock&)[使用_Mutex=std::Mutex]'
这个编译器错误尤其令人困惑,因为它指向包含
lock(l),access(a)
的行,我正试图使用std::unique\u lock的已删除副本构造函数。我将
l
声明为
锁&&
,那么我怎么可能调用复制构造函数呢


我在internet上找到的大多数资源似乎都表明可以使用std::move移动唯一的_锁,尽管似乎没有人解决如何使用std::move构造包含唯一_锁的对象的问题。我在这里做错了什么?

问题:

LockedListAccess(lock_t&& l, std::list<T>& a) 
    : lock(std::move(l))
    , access(a) 
{}
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) 
{}
可以变成这样:

LockedListAccess locked() {
    return LockedListAccess{ lock_t{mutex}, underlying_list }
}

哇,这是一个奇怪的语言“特性”。我从来没有想到声明的
lock\u t&
会突然变成
lock\u t&
,仅仅因为它在构造函数中。而且似乎没有必要移动已经是右值的东西。谢谢你教我另一个C++奇遇,它不变成<代码>锁和< /代码>。它仍然是绑定到临时对象的r值引用,但用作l值。这一点一开始让我很困惑,但如果你知道什么是l值的话,实际上是有道理的。即:任何被命名的东西都很可能是一个l值,而你的
锁&
有一个名为
l