模板赋值运算符重载之谜
Posted
技术标签:
【中文标题】模板赋值运算符重载之谜【英文标题】:Template assignment operator overloading mystery 【发布时间】:2011-08-03 07:18:57 【问题描述】:我有一个简单的结构Wrapper
,以两个模板化的赋值运算符重载来区分:
template<typename T>
struct Wrapper
Wrapper()
template <typename U>
Wrapper &operator=(const Wrapper<U> &rhs)
cout << "1" << endl;
return *this;
template <typename U>
Wrapper &operator=(Wrapper<U> &rhs)
cout << "2" << endl;
return *this;
;
然后我声明a和b:
Wrapper<float> a, b;
a = b;
将b
赋值给a
将使用上面的非常量模板赋值运算符重载,并显示数字“2”。
让我困惑的是:如果我声明c
和d
,
Wrapper<float> c;
const Wrapper<float> d;
c = d;
并将d
赋值给c
,两个赋值运算符重载都不用,也不显示输出;因此调用了默认的复制赋值运算符。为什么将d
分配给c
不使用提供的 const 重载赋值运算符?或者相反,为什么将b
分配给a
不 使用默认的复制赋值运算符?
【问题讨论】:
【参考方案1】:为什么将
d
赋值给c
不使用提供的 const 重载赋值运算符?
隐式声明的复制赋值运算符,声明如下:
Wrapper& operator=(const Wrapper&);
运算符模板不会抑制隐式声明的复制赋值运算符的生成。由于参数(一个 const 限定的 Wrapper
)与此运算符的参数 (const Wrapper&
) 完全匹配,因此在重载决策期间选择它。
没有选择操作符模板并且没有歧义,因为 - 在所有其他条件相同的情况下 - 在重载决策期间,非模板比模板更匹配。
为什么将
b
赋值给a
不使用默认的复制赋值运算符?
与隐式声明的复制赋值运算符(采用const Wrapper<U>&
)相比,参数(非 const 限定 Wrapper
)更适合采用 Wrapper<U>&
的运算符模板。
【讨论】:
+1 for 运算符模板不会抑制隐式声明的复制赋值运算符的生成。【参考方案2】:来自 C++03 标准,§12.8/9:
用户声明的复制赋值运算符
X::operator=
是类X
的非静态非模板 成员函数,只有一个X
、X&
、@ 类型的参数987654325@、volatile X&
或const volatile X&
。
第 12.8/10 条:
如果类定义没有显式声明复制赋值运算符,则隐式声明一个。
operator=
是模板这一事实使其不是复制赋值运算符,因此类的隐式复制赋值运算符仍由编译器生成。
【讨论】:
如果不是复制赋值运算符,那它是什么?那么你应该怎么做——只做一个 CopyFrom 函数模板或类似的东西? @DavidDoria :这是一个赋值运算符,而不是 copy 赋值运算符。以上是关于模板赋值运算符重载之谜的主要内容,如果未能解决你的问题,请参考以下文章