catalog
默认模板参数
template< class _T>
void F(){
return;
}
此时, F()
是错误的, 必须要有模板参数;
template< class _T = void>
void F(){
return;
}
= void
就是默认值, 此时F()
也可以了.
函数模板的参数, 必须和(主模板)参数 完全匹配
不要忘记, 函数只有 (全特化)
template <class T> void func( T t){
}
template <> void func< int>( int t){
}
template <> void func< int>( int t){
}
你写成: <int>( int & t)
<int>( char t)
<int &>( int t)
都是错的!!! 这里非常非常重要!!! 仔细理解
因为, 主模板函数 只有一个T
, 你在全特化时<x>( y t){}
, 最终x 和 y
都会变成同一个T
, 所以, x
和 y
, 必须严格相同
函数的 重载 与 全特化
template <class T> void func( T t){
} ' 111 '
template <class T> void func( ST<T> t){
} ' 222 '
template <> void func< int>( int t){
} ' 333 '
template <> void func< int>( ST< int> t){
} ' 444 '
首先, 1 和 2, 都是主模板函数, 1 和 2, 构成: 函数重载
一定要注意 函数重载
这个概念!! 函数重载是一个很大的概念!
比如, 你有n个函数重载, 每一个重载函数, 都可以拓展出 一系列的(全特化)… n个函数重载, 就意味着: 有n个 不同的 全新的 函数!!!
3是1的全特化, 4是2的全特化; 但3和4, 不是全新的函数, 他们归根结底 还是1和2的类型!!
拓展知识:
我们知道, std里面 不允许添加新的东西!!!
换句话说: 可以全特化std的函数, 但不可以重载std的函数!!! 因为, 重载 意味着 添加新东西了
namespace std{
template <class T> void swap( T &, T &); ' 这是std的官方函数 '
}
如果你新加了:
namespace std{
template <class T> void swap( ST< T> & a, ST< T> & b); ' 语法上可行 '
}
但是, 这个模板函数, 与原本的std::swap
是 重载关系!! 不是特化关系!! 这违背了: std的不可以添加 新的东西!!!
全特化, 偏特化
全特化: 只要有template<>
就是全特化
- 函数全特化
这里的函数, 包括: 全局函数, 类的成员函数
template <class T> void func(){ } template <> void func< int>(){ } ' 全特化 '
- 类的全特化
template <class T> class STT{ }; template <> class STT<int>{ };
偏特化: 只有类模板, 才允许偏特化!!!
模板类的模板函数, 也不可以偏特化!!!只要是函数, 不管什么函数, 都不允许偏特化
template <class T, class TT> class ST{
};
template <class T> class ST<T, int>{
}; ' 个数上的 偏特化 '
template <class T, class TT> class ST<T &, TT>{
}; ' 类型(const/ &/ */ volatile)上的 偏特化'
template <class T, class TT> class ST< Obj1<T> , Obj2<TT> >{
};
' 请注意这种写法!!! 也属于(类型上的) 偏特化 '
模板函数的声明和定义, 必须在同个文件里
A.h
template <class T> extern void Func( T t); ' 模板函数 - primary '
template <class T> extern void Func( O< T>); ' 模板函数 - partial '
template <class T> class O{
' 模板类 '
public:
O();
void func();
template <class TT> void ffunc( TT t);
};
A.cpp
template <class T> void Func( T t){
...}
template <class T> void Func( O< T>){
...}
template <class T> O< T>::O(){
...}
template <class T> void O< T>::func(){
...}
template <class T> template <class TT> void O< T>::ffunc( TT t){
...}
对于普通函数, 这样写肯定是正确的; 但是, 对于模板函数, 这样是报错的!!!
你必须把A.cpp里的 所有代码, 写到 A.h里;
所谓, 写到A.h里, 有两种实现方式
- 要么 A.h里是:
即, A.h 原封不动, 直接放到他下面即可template <class T> extern void Func( T t); template <class T> void Func( T t){ ...}
- 要么 A.h 里是:
template <class T> void Func( T t){ ...}
两种写法都是完全等价的; 方式一看起来更简洁些.
为什么呢?
对于 非模板的函数, 他有两个步骤: (声明extern) 和 (定义/实现)
但是, 对于模板函数, 他有三个步骤: (声明) 和 (定义) 和 (实现)
你的template< T> Func( T t){ ... }
, 其实是定义, 不是(实现)!!!
这个 (实现), 又分为两种
- 1: 全特化, 即这个完整的(实现),