如何利用模板复制&移动构造函数和赋值运算符?
Posted
技术标签:
【中文标题】如何利用模板复制&移动构造函数和赋值运算符?【英文标题】:How to utilize template copy&move constructor and assignment operator? 【发布时间】:2019-05-31 17:32:27 【问题描述】:考虑以下 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);
UPDATE1:我需要模板复制和移动构造函数和赋值运算符,因为模板参数实际上只是控制一些缓存,所以A<T1>
可以安全地分配给A<T2>
。
【问题讨论】:
复制/移动构造函数永远不是模板。如果您不希望复制/移动构造函数完成工作,也许您可以委托。显示实施的哪一部分让您感到困扰;它可能最好放在任何构造函数之外。A<int> a1();
是一个函数声明(“最烦人的解析...”)而且所有的构造函数都是私有的
而不是 delete
常规的复制/移动构造函数/赋值,将它们转发到模板实现。
@Jarod42,你说的转发具体是什么意思?看来这就是我要的 - 如何转发。
@SergeRogatch - 您可以在模板构造函数中转发添加未使用的参数(具有默认值)
【参考方案1】:
您可以通过使用替代签名声明已删除的复制构造函数/赋值运算符来使编译器满意,这不会导致选择此重载,但会阻止编译器生成构造函数/赋值运算符:
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> a2a1;
return 0;
online compiler
15.8.1 复制/移动构造函数 [class.copy.ctor] 1.
class X
的非模板构造函数是一个拷贝构造函数,如果它的第一个参数是X&
、const X&
、volatile X&
或const volatile X&
类型,或者没有其他参数或者所有其他参数有默认参数
【讨论】:
【参考方案2】:使用第二个未使用(和默认)参数将执行委托给模板构造函数的复制构造函数的最小示例
#include <iostream>
template <typename T>
struct A
A()
A (A const & a0) : Aa0, 0
template<typename U>
A (A<U> const &, int = 0)
std::cout << "template constructor" << std::endl;
;
int main()
A<int> a0;
A<int> a1a0;
-- 编辑--
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 所建议的(谢谢),直接从非模板中调用模板运算符
template <typename U>
A & operator= (A<U> const & a0)
/* do assignment */ return *this;
A & operator= (A const & a0)
return operator=<T>(a0);
【讨论】:
operator=
怎么样?尝试添加虚拟参数会导致编译器错误 binary 'operator =' has too many parameters
和 'operator =' cannot have default parameters
@SergeRogatch - 答案改进;希望这会有所帮助。
@max66: 或return operator=<T>(rhs);
.
@Jarod42 - 你是对的:有效而且更简单。谢谢。以上是关于如何利用模板复制&移动构造函数和赋值运算符?的主要内容,如果未能解决你的问题,请参考以下文章