问题
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>
.
回答1:
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 forclass X
is a copy constructor if its first parameter is of typeX&
,const X&
,volatile X&
orconst volatile X&
, and either there are no other parameters or else all other parameters have default arguments
回答2:
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 errorsbinary '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); }
来源:https://stackoverflow.com/questions/54050890/how-to-utilize-template-copymove-constructor-and-assignment-operator