为什么 std::unique_lock 同时提供模板和 MoveConstructible

How come std::unique_lock offers template and MoveConstructible at the same time?

本文关键字:MoveConstructible unique std lock 为什么      更新时间:2023-10-16

我读到移动赋值运算符和复制赋值运算符是非模板和非静态成员函数。
如果是这种情况,std::unique_lock怎么可能同时进行移动和模板化?
我可以看到std::unique大量使用模板。
我在这里错过了什么吗?

std::mutex m;
std::unique_lock<std::mutex>  lock_a(m, std::defer_lock);
                   ^^^

好的,要回答这个问题,有必要精确地了解模板术语。我看到的有帮助的一件事是尽可能晚地说"模板"这个词。所以我们有,与这个问题相关的类模板template <typename T1> class class_template { /* ... */ };,和成员函数模板class non_template { public: template<typename T2> void member_function_template(T2& arg); };

此外,类模板可以具有成员函数模板:template <typename T3> class also_class_template { public: template<typename T4> void also_member_function_template(T4& arg2); };

好的,处理完这个问题,我们就可以进入问题的实质。类或类模板如何以及为什么同时提供 MoveConstructable 和模板构造?

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) { /* ... */ }
};

答:类或类模板提供重载构造函数,其中一个是移动构造函数,另一个是构造函数模板(成员函数是构造函数的成员函数模板)。

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

我读到移动赋值运算符和复制赋值运算符是非模板和非静态成员函数。

它们可以是模板成员方法。
举一个最小的工作示例:

#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);
}

也就是说,问题的其余部分毫无意义。

相关文章:
  • 没有找到相关文章