条款45:运用成员函数模板接受所有兼容类型
例:
template<typename T>
class A{
public:
template<typename Y>
void func1(A<Y>& y1);
A(const A& a); //复制构造函数
template<typename Y>
A(const A<Y>& a); //泛化复制构造函数
};
解释:类型为T的模板类A成员函数func1中引入类型为Y的模板类A,因此该函数可以处理与T兼容的所有类型。
总结:
条款46:需要类型转换时为模板定义非成员函数
1、序言:
条款24讨论了:为什么只有non-member函数才能在所有实参身上添加隐式类型转换(因为:类成员函数只能接受函数参数的隐式转换而对调用者this的类型不能转换)条款24
例:
template<typename T>
class A{
public:
A(const T& t);
};
template<typename T>
const A<T> operator* (const A& l,const A& r){...} //non-member模板函数
//.cpp
A<int> a(4);
A<int> res = a*2; //编译失败,2转换为A<int>对象失败
编译失败原因:
C++规定非成员模板函数的template实参推到过程中从不将隐式类型转换纳入考虑。
**2、解决方法:**声明为类的friend模板函数,例:
template<typename T>
class A{
public:
A(const T& t);
friend const A<T> operator* (const A<T>& l,const A<T>& r){...}
//友元模板函数
friend const A operator* (const A& l,const A& r){...} //两函数相同,后续解释
};
//.cpp
A<int> a(4);
A<int> res = a*2; //编译失败,2转换为A<int>对象失败
成功原因:
1、在类A
用int
实例化时,友元函数operator*
也被实例化,参数确定为A<int>
,此时其不再是模板函数,变成了普通函数,因此可以接受函数参数的隐式转换。
2、该友元函数定义要写在该类中,因为编译器在类A实例化时利用int在类A<int>
中声明了该函数,因此定义也需要在该类中。
小知识点:
1、此处的friend用途与传统不同,传统用其访问类的non-public成员,这里使用友元模板函数使函数在模板类具体化时自动具体化。
2、在class template中,template名(类名)可被用来作为template及其参数的缩略表达方法,如A代替A<T>
.。
总结:
1、当编写类模板时,函数需要支持模板相关隐式类型转换时,需要将此函数声明为firend函数,让其随模板类自动具体化,因为C++规定template实参推到过程中从不将隐式类型转换纳入考虑。。
2、在class template中,template名(类名)可被用来作为template及其参数的缩略表达方法,如A代替A<T>
.。