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

时间:2016-07-17 07:30:04

标签: c++ c++11

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

std::mutex m;

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

2 个答案:

答案 0 :(得分:2)

好的,要回答这个问题,有必要准确了解模板术语。我所看到的有一点帮助就是说&#34;模板&#34;尽可能晚。因此,我们与此问题相关的是类模板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) { /* ... */ }
};

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

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

答案 1 :(得分:1)

  

我读过Move赋值运算符和Copy赋值运算符是非模板和非静态成员函数。

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

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

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