Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to utilize template copy&move constructor and assignment operator?

Consider the following C++ code with my failed attempt to avoid 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 */ }        
};

However, I get the following error

attempting to reference a deleted function

when trying to push A items to a vector or simply copy-construct like:

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

UPDATE1: I need template copy&move constructors and assignment operators, because the template argument really just controls some caching, so A<T1> can be safely assigned to A<T2>.

like image 536
Serge Rogatch Avatar asked Jan 05 '19 10:01

Serge Rogatch


People also ask

How can a template be useful?

Templates encourage repeatability and efficiency. Reworking your documents/spreadsheets for every project or proposal wastes valuable time and money. Instead, focus on content and completing tasks. Templates can be utilized and customized for various purposes and audiences.

How do I apply a template to an existing document?

Open the Word document you would like to apply the template to, then click File > Options to open the Word Options dialog box. 2. In the Word Options dialog box, (1) click Add-ins in the left bar, (2) select Templates from the Manage drop down list, and (3) click Go.

How do I copy and paste a template?

Press Ctrl+A to select the entire document, and press Ctrl+C to copy it. (With buttons, Home > Select > Select All, and then Home > Copy.) Press Ctrl+End to go to the end of the document, which will be on the second page, and press Ctrl+V to paste (or Home > Paste).

How do I use a document template in Word?

Find and apply a templateOn the File tab, click New. Under Available Templates, do one of the following: To use one of the built-in templates, click Sample Templates, click the template that you want, and then click Create.


2 Answers

You can make compiler happy by declaring deleted copy constructor / assignment operator with alternative signature which will not cause this overload to be selected but will prevent generation of constructor / assignment operator by compiler:

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 Copy/move constructors [class.copy.ctor]
1. A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments

like image 134
user7860670 Avatar answered Oct 05 '22 09:10

user7860670


A minimal example of a copy constructor that delegate the execution to the template constructor using a second unused (and defaulted) argument

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

-- EDIT --

The OP asks

What about operator=? Trying to add a dummy parameter gives compiler errors binary 'operator =' has too many parameters and 'operator =' cannot have default parameters

For operator=() I propose to "delegate" (not in the meaning of delegating constructor, in this case) both operators to a normal method; a template one.

Something as

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

Maybe the assign() method can be a private one.

Or better, as suggested by Jarod42 (thanks), directly calling the template operator from the not-template one

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

A & operator= (A const & a0)
 { return operator=<T>(a0); }
like image 21
max66 Avatar answered Oct 05 '22 09:10

max66