`计算机知识` `C++` 全特化, 偏特化, template泛型模板编程,实参推演,可变长模板函数,模板函数的.h声明与.cpp实现

默认模板参数

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, 所以, xy, 必须严格相同

函数的 重载 与 全特化

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里是:
    template <class T> extern void Func( T t);
    
    template <class T> void Func( T t){
          ...} 
    
    即, A.h 原封不动, 直接放到他下面即可
  • 要么 A.h 里是:
    template <class T> void Func( T t){
          ...} 
    

两种写法都是完全等价的; 方式一看起来更简洁些.


为什么呢?

对于 非模板的函数, 他有两个步骤: (声明extern) 和 (定义/实现)

但是, 对于模板函数, 他有三个步骤: (声明) 和 (定义) 和 (实现)

你的template< T> Func( T t){ ... }, 其实是定义, 不是(实现)!!!

这个 (实现), 又分为两种

  • 1: 全特化, 即这个完整的(实现),
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值