(二)类模板、函数模板、成员模板、特化与泛化、模板模板参数
作者:互联网
类模板与函数模板
- 类模板
template <typename T>
class complex
{
public:
...
private:
T re, imag;
...
};
- 函数模板
template<class T>
inline
const T& min(const T& a, const T& b)
{
return b < a ? b : a;
}
- 成员模板
- 类是一个模板,类的成员是另一个模板,二者可以不同步变化,但是在成员的类型要可以向类的类型转化。
- 广泛出现在标准库中类的构造函数中,为了让类的构造函数更有弹性
template<class T1, class T2>
struct pair{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair()
: first(T1()), second(T2()) { }
pari(const T1& a, const T2& b)
: first(a), second(b) { }
//------------------------------------------------------------
//成员模板
template<class U1, class U2>
pair(const pair<U1, U2>& p)
:first(p.first), second(p.second) { }
//p的第一个元素放到pair的第一个元素,p的第二个元素放到pair的第二个元素,这种赋值方式要求U可以向T转化
//如p的类型中U1是T1的派生类,U2是T2的派生类,可以将p赋值给它的基类构成的pair
//------------------------------------------------------------
};
//智能指针使用成员模板实现将基类指针指向派生类
template<typename _Tp>
class shared_ptr: public __shared_ptr<_Tp>
{
...
template<typename _Tp1>
explicit shared_ptr(_Tp1* __p)
: __shared_ptr<_Tp>(__p){}
...
};
--------------------------使用-------------------------------
Based* ptr = new Derived1;
shared_ptr<Base1> sptr(new Derived1);
specialization特化
- 泛化是特化的反面,泛化就是模板,即有一个类型,在使用时再指定具体是什么
- 特化就是将模板的一部分具特征化,即对某些类型做特殊的设计
- 全特化就是为所有的模板参数都设计特殊值
- 偏特化分为两种,一种是个数上的偏,另一种是范围上的偏
- 函数模板只有全特化,类模板可以偏特化和全特化
- 泛化和特化示例
- 求两点之间直线上的坐标点,这些点的坐标都是实数,为此写一个模板类
- 在电脑屏幕上坐标的取值只能是整数,为此写一个算法能大大提高计算效率
//泛化
template<class Key>
struct hash { };
//特化
template<>
struct hash<char> {
size_t operator() (char x) const { return x; }
};
template<>
struct hash<int> {
size_t operator() (int x) const { return x; }
};
template<>
struct hash<long> {
size_t operator() (long x) const { return x; }
};
//使用
cout<<hash<long>()(1000);//使用char版本的特化
- 特化的优先级高于泛化
- 泛化又称作全泛化,对应的是偏特化
个数上的偏特化
- 为什么要偏特化,因为编译器认为,对于某一功能,如果有更好的实现,就该优先使用该实现
- 下例中模板有两个模板参数,c++中最小单元的元素类型是char,大小是一个字节(8位),如果让一个字节去代表一个bool值,太浪费了。为bool类型专门设计一套,即设计第一个参数绑定为bool的偏特化模板
- 偏特化的绑定要是连续的,如果第一个模板参数绑定了,后续的参数也要绑定,或者有默认值
template<typename T, typename Alloc=......>
class vector
{
...
};
//个数上的偏特化
template<typename Alloc=......>
class vector<bool, Alloc>
{
...
};
范围上的偏特化
- 对于一个任意T类型的模板,如果想对指针类型设置效率更高的版本,可设置该模板的偏特化指针版本
template <typename T>
class C
{
...
};
//范围偏特化
template <typename T>
class C<T*>
{
...
};
------------------------测试实例---------------------------
C<string> obj1;//使用普通版本
C<string*> obj2;//使用偏特化版本
模板模板参数
- 模板参数是模板,则为模板模板参数
//Container的参数是第一个参数
template<typename T,
template <typename T>
class Container
>
class XCLs
{
private:
Container<T> c;
public:
...
};
//using别名
template<typename T>
using Lst = list<T, allocator<T>>;
//希望使用者可以实现,传入一个容器并且传入容器的元素类型
//使用会更加灵活
XCLs<string, list> mylst1;//错,容器需要多个模板参数
//容器有第二模板参数,有的还有第三模板参数,平常使用中是有默认值的
//直接使用无法通过编译
//必需使用using声明起别名
XCLs<string, Lst> mylst2;
- 示例二
//模板模板参数
template<typename T,
template <typename T>
class SmartPtr
>
class XCls
{
private:
SmartPtr<T> sp;
public:
XCLs() : sp(new T) { }
};
------------------------------------------------------------
XCls<string, shared_ptr> p1;
XCls<double, unique_ptr> p2;//错
XCls<int, weak_ptr> p3;//错
XCla<long, suto_ptr> p4;
- 非模板模板参数
template<class T, class Sequence = deque<T>>//不是模板模板参数
class stack{
friend bool operator== <> (const stack&, const stack&);
friend bool operator< <> (const stack&, const stack&);
protected:
Sequence c;//底层容器
...
};
stack<int> s1;
stack<int, list<int>> s2;//它的第二个模板参数已经写死了,它不再是模板
标签:const,泛化,参数,template,class,模板,特化 来源: https://blog.csdn.net/weixin_45781228/article/details/120486663