首页 > 解决方案 > 如何使用模板复制&移动构造函数和赋值运算符?

问题描述

考虑以下 C++ 代码以及我尝试避免优先使用非模板复制和移动构造函数和赋值运算符的失败:

template<typename T> class A {
public:
    A() { /* implementation here */ }

    // Remove from the overloads the default copy&move constructors and assignment operators
    A(const A&) = delete;
    A& operator=(const A&) = delete;
    A(A&&) = delete;
    A& operator=(A&&) = delete;

    // I want these to be used e.g. by std::vector
    template<typename U> A(const A<U>& fellow) { /* implementation here */ }
    template<typename U> A& operator=(const A<U>& fellow) { /* implementation here */ }

    template<typename U> A(A<U>&& fellow) { /* implementation here */ }
    template<typename U> A& operator=(A<U>&& fellow) { /* implementation here */ }        
};

但是,我收到以下错误

试图引用已删除的函数

当尝试将A项目推送到向量或简单地复制构造时,例如:

A<int> a1{};
A<int> a2(a1);

UPDATE1:我需要模板复制和移动构造函数和赋值运算符,因为模板参数实际上只是控制一些缓存,所以A<T1>可以安全地分配给A<T2>.

标签: c++templatescopy-constructorassignment-operatordefault-constructor

解决方案


您可以通过使用替代签名声明已删除的复制构造函数/赋值运算符来使编译器满意,这不会导致选择此重载,但会阻止编译器生成构造函数/赋值运算符:

template<typename T> class A
{ public:
    A() { /* implementation here */ }

    // Remove from the implicit declaration of the default copy&move constructors and assignment operators
    A(A volatile const &) = delete;
    A & operator =(A volatile const &) = delete;

    // I want these to be used e.g. by std::vector
    template<typename U> A(A<U> const & fellow) { /* implementation here */ }
    template<typename U> A & operator =(A<U> const & fellow) { /* implementation here */ return *this;}

    template<typename U> A(A<U> && fellow) { /* implementation here */ }
    template<typename U> A & operator =(A<U> && fellow) { /* implementation here */ return *this; }        
};
int main()
{
    A<int> a1{};
    A<int> a2{a1};
    return 0;
}

在线编译器

15.8.1 复制/移动构造函数 [class.copy.ctor]
1. 如果非模板构造class X函数的第一个参数是、或类型X&,并且没有其他参数或者所有其他参数都有默认参数const X&volatile X&const volatile X&


推荐阅读