代码之家  ›  专栏  ›  技术社区  ›  Serge Rogatch

如何利用模板复制和移动构造函数和赋值运算符?

  •  5
  • Serge Rogatch  · 技术社区  · 7 年前

    考虑下面的C++代码,我尝试失败 preference of non-template copy&move constructors and assignment operators :

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

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

    2 回复  |  直到 7 年前
        1
  •  5
  •   user7860670    7 年前

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

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

    online compiler

    15.8.1复制/移动构造函数[class.Copy.ctor]
    1.用于 class X 如果其第一个参数的类型为 X& , const X& , volatile X& 或 const volatile X& ,并且要么没有其他参数,要么所有其他参数都有默认参数

        2
  •  1
  •   max66    7 年前

    复制构造函数的一个最小示例,它使用第二个未使用(且默认)的参数将执行委托给模板构造函数

    #include <iostream>
    
    template <typename T>
    struct A
     {
       A()
        { }
    
       A (A const & a0) : A{a0, 0}
        { }
    
       template<typename U>
       A (A<U> const &, int = 0)
        { std::cout << "template constructor" << std::endl; }
     };
    
    int main()
     {
       A<int>  a0;
       A<int>  a1{a0};
     }
    

    --编辑--

    OP问道

    那么...怎么样 operator= ? 尝试添加伪参数会导致编译器错误 binary 'operator =' has too many parameters and 'operator =' cannot have default parameters

    对于 operator=() 我建议将两个操作符“委托”(在本例中,不是委托构造函数的意思)给一个普通方法;一个模板。

    比如

       template <typename U>
       A & assign (A<U> const &)
        { /* do assignment */ return *this; }
    
       A & operator= (A const & a0)
        { return assign(a0); }
    
       template <typename U>
       A & operator= (A<U> const & a0)
        { return assign(a0); }  
    

    也许是 assign() 方法可以是 private 一

    或者更好,正如Jarod42(谢谢)所建议的那样,直接从not template操作符调用template操作符

    template <typename U>
    A & operator= (A<U> const & a0)
     { /* do assignment */ return *this; }
    
    A & operator= (A const & a0)
     { return operator=<T>(a0); }