模板赋值操作符重载之谜
Template assignment operator overloading mystery
我有一个简单的结构体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
而不是使用默认的复制赋值操作符?
为什么将
d
赋值给c
不使用提供的const重载赋值操作符?
仍然生成隐式声明的复制赋值操作符,声明如下:
Wrapper& operator=(const Wrapper&);
操作符模板不抑制隐式声明的复制赋值操作符的生成。由于实参(const限定的Wrapper
)与该操作符的形参(const Wrapper&
)完全匹配,因此在重载解析期间选择它。
操作符模板没有被选中,并且没有歧义,因为在其他条件相同的情况下,在重载解析过程中,非模板比模板更适合匹配。
为什么将
b
赋值给a
不使用默认的拷贝赋值操作符?
实参(非const限定的Wrapper
)比隐式声明的复制赋值操作符(接受const Wrapper<U>&
)更适合接受Wrapper<U>&
的操作符模板。
来自c++ 03标准,§12.8/9:
用户声明的复制赋值运算符
X::operator=
是X
类的非静态非模板成员函数,只有一个形参类型为X
、X&
、const X&
、volatile X&
或const volatile X&
。
和§12.8/10:
如果类定义没有显式声明复制赋值操作符,则隐式声明。
事实上,你的operator=
是一个模板,使得不是一个复制赋值操作符,所以类的隐式复制赋值操作符仍然是由编译器生成的。
- c++中的重载赋值操作符
- 复制构造函数,赋值操作符重载
- c++复制构造函数,重载赋值操作符,方法get()
- 赋值操作符重载
- 当类是子类时重载赋值操作符
- 模板类的重载赋值操作符
- 使用重载赋值操作符
- 类和向量的重载赋值操作符
- 在可强制转换为另一个模板类型的类模板中重载赋值操作符
- 无法重载赋值操作符
- c++ const重载赋值操作符机制
- 创建了自己的字符串类——重载赋值操作符和析构函数的错误
- 在重载赋值操作符内调用构造函数
- 使用重载赋值操作符克隆单链表
- 类型演绎的重载赋值操作符
- 重载赋值操作符,留下基本功能
- 重载赋值操作符总线错误
- 退出重载赋值操作符将调用析构函数来删除对象
- 重载赋值操作符而不知道类结构
- 重载赋值操作符和其他操作符的区别是什么?