Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::unique_lock同时提供模板和可移动构造?_C++_C++11 - Fatal编程技术网

C++ 为什么std::unique_lock同时提供模板和可移动构造?

C++ 为什么std::unique_lock同时提供模板和可移动构造?,c++,c++11,C++,C++11,我了解到移动分配运算符和复制分配运算符是非模板和非静态成员函数。 如果是这种情况,std::unique_lock如何能够同时进行移动和模板化? 我可以看到std::unique大量使用模板。 我是不是遗漏了什么 std::mutex m; std::unique_lock<std::mutex> lock_a(m, std::defer_lock); ^^^ std::mutexm; std::unique_lock_a(m,std::d

我了解到移动分配运算符和复制分配运算符是非模板和非静态成员函数。
如果是这种情况,
std::unique_lock
如何能够同时进行移动和模板化?
我可以看到
std::unique
大量使用模板。
我是不是遗漏了什么

std::mutex m;

std::unique_lock<std::mutex>  lock_a(m, std::defer_lock);
                   ^^^
std::mutexm;
std::unique_lock_a(m,std::defer_lock);
^^^
我了解到移动赋值运算符和复制赋值运算符是非模板和非静态成员函数

它们可以是模板成员方法。
作为一个最低限度的工作示例:

#include<type_traits>
#include<utility>
#include<iostream>

template<typename T>
struct S {
    template<typename U>
    friend class S;

    S() { t = new T; }
    ~S() { delete t; }

    S& operator=(S &&o) {
        std::cout << "non-template move" << std::endl;
        std::swap(t, o.t);
        return *this;
    }

    S& operator=(const S &o) {
        std::cout << "non-template copy" << std::endl;
        t = o.t;
        return *this;
    }

    template<typename U, std::enable_if_t<std::is_convertible<U, T>::value>* = nullptr>
    S& operator=(S<U> &&o) {
        std::cout << "template move" << std::endl;

        if(t != o.t) {
            delete t;
            t = std::move(o.t);
            o.t = nullptr;
        }

        return *this;
    }

    template<typename U, std::enable_if_t<std::is_convertible<U, T>::value>* = nullptr>
    S& operator=(const S<U> &o) {
        std::cout << "template copy" << std::endl;
        t = o.t;
        return *this;
    }

private:
    T *t;
};

struct A {};
struct B: A {};

int main() {
    S<B> s1;
    S<B> s2;
    S<A> s3;

    s2 = s1;
    s3 = s2;
    s2 = std::move(s1);
    s3 = std::move(s2);
}
#包括
#包括
#包括
模板
结构{
模板
朋友班;
S(){t=new t;}
~S(){delete t;}
S&o运算符=(S&o){

好的,要回答这个问题,有必要对模板术语进行精确的描述。我看到的一件事是尽可能晚地说“模板”这个词。因此,与这个问题相关的是,我们有class templates
template class_template{/*…*/};
,以及成员函数模板
类非_模板{public:template void member _函数_模板(T2&arg);};

此外,一个类模板可以有一个成员函数模板:
模板类也\u类\u模板{public:template void也\u成员函数\u模板(T4&arg2);};

好的,处理完这些,我们就可以进入问题的核心了。类或类模板如何以及为什么同时提供可移动构造和模板构造

template<typename T5> class answer_manifest {
public:
  // move constructor
  answer_manifest(answer_manifest&& move_from) { /* ... */ }

  // constructor template that cannot be the move constructor
  template<typename T6> answer_manifest(T6&& template_move_from) { /* ... */ }
};
模板类答案\u清单{
公众:
//移动构造函数
应答清单(应答清单和移动清单){/*…*/}
//无法作为移动构造函数的构造函数模板
模板应答清单(T6和模板移动){/*…*/}
};
答:类或类模板提供重载构造函数,其中一个是移动构造函数,另一个是构造函数模板(成员函数是构造函数的成员函数模板)


现在,这提出了一个后续问题,为什么我们需要两者?因为标准规定,构造函数或赋值运算符的成员函数模板永远不会被视为移动(或复制)构造函数或赋值运算符。其原因是允许编写具有模板化构造函数的不可复制类(在这种情况下,您将如何防止复制?).

该类是一个模板类。它的成员函数不必是模板类。这并不重要,移动构造函数和移动赋值运算符只是普通的成员函数,可以像其他任何成员函数一样是模板成员函数。@JoachimPileborg,你是说移动赋值运算符可以模板化吗?@Pocke:不,类型是非模板移动分配运算符所属的必须是可以模板化的。请注意,您也可以使用模板化的分配运算符进行移动,而不是“移动分配运算符”s、 @ildjarn所以在unique_lock中有一个模板化的赋值运算符使unique_lock可移动吗?@pocke:有一个非模板移动赋值运算符,允许从相同类型的其他
unique_ptr
移动,还有一个模板化赋值运算符,允许从其他
unique_ptr
移动>s的兼容类型。后者是移动的赋值运算符,但不是移动赋值运算符。好了,现在它有意义了。我想我主要是混淆了赋值运算符和成员函数模板赋值运算符。所以是的,您的代码显示成员函数模板移动赋值运算符是可能的,所以我是ong.只是好奇为什么你在其中一个中使用swap,在另一个中使用std::move?@pocke在第一种情况下,两个
t
都有相同的类型。在第二种情况下,它们有不同的类型,但我知道一个可以转换为另一个。因此,在第一种情况下,我可以交换它们,而在第二种情况下,将一个放到d更安全iscard并移动另一个。请您也在上面的示例中添加模板赋值运算符,以便我也可以执行s2=s4,我指的是带有single&的赋值运算符,因为当我尝试添加时,会出现错误,称“operator=”的重载不明确@pocke Updated answer。您要接受吗?