博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模板的进阶 非类模板参数 类模板的特化
阅读量:6021 次
发布时间:2019-06-20

本文共 2621 字,大约阅读时间需要 8 分钟。

模板的进阶
非类模板参数
类模板的特化
静态数组:array:template < class T, size_t N > class array; array为可以存放N个元素的数组模拟实现:
#include<iostream>
using namespace std;
namespace bit{
template < class T, size_t N > ;
class array{
    public:
    private:
        //T类型参数,N非类型参数
        T array[N];   
    };
}
 
int main(){
    bit::array<int,10> a;
    return 0;
}
 
    模板---->任意类型都可以处理
    特化---->对模板不能处理或者处理有误的类型进行特殊化处理(比如对于char *类型,是一个字符串,比较时应该通过字符串的方法进行比较,但是通过这个模板进行比较时直接用大于小于><进行比较,所以需要对模板进行特化)
        1.必须提供一个类模板(对于函数模板,一般不进行特化)
        
template<class T>
T& Max(
T& a,
T& b){
    return a>b?a:b;
}
template<>
char *& Max<
char *>(char *& left,char *& right){
    //不能加const,否则会出错,报错:不是函数模板的专用化
    //加了之后对于特化的成本增加了
    //如果处理不了,直接给出这种处理的函数即可,不需要特化
    if(strcmp(left,right)>0){
        return left;
    }
    retrun right;
}
 
int main(){
    int a=0;
    int b=3;
    cout<<Max(a,b)<<endl;
    char *p1="hello";
    char *p2="world";
    cout<<Max(p1,p2)<<endl;
    return 0;
}
 
类模板的特化:
    1.全特化:类模板实例化期间将类型全给出来比如:class Data<int , double>
    2.偏特化(1)部分特化:class Data<int ,T>
                   (2)   让模板的参数列表中的类型参数限制更加严格class Data<T*,T*>
应用场景:识别被拷贝的元素的类型是内置类型还是用户自定义类型?
                内置类型:不会涉及资源的管理
                自定义类型:会涉及类型的管理
    类型萃取:
        
//实现通用的拷贝函数:
template<>
                                              
//内置类型
struct TypeTraits<char>{
    typedef TrueType POD_TYPE;
};
 
template<>
struct TypeTraits<double>{
    typedef TrueType POD_TYPE;
};
 
struct TypeTraits<int>{
    typedef TrueType POD_TYPE;
};
 
template<>
struct TypeTraits<float>{
    typedef TrueType POD_TYPE;
};
                                             
//是实现的通用的类型,进而判断是内置类型还是自定义类型
                                             
 
template<>
struct TypeTraits<T>{
    typedef FalseType POD_TYPE;
};
                                           
 
struct TrueType{
    static bool Get(){
        return true;
    }
};//
代表内置类型
 
struct FalseType{
    static bool Get(){
        return false;
    }
};//
代表自定义类型
 
    
template<class T>
void Copy(T* dst,T* src,size_t size){
    if(TypeTraits<T>::POD_TYPE::Get()){
        memset(dst,src,sizeof(T)*size);
    }
    else{
        for(i=0;i<size;++i){
            dst[i]=src[i];
        }
}

模板的分离编译:
    预处理阶段---->编译---->汇编---->链接---->可执行程序
    1.预处理 宏替换,宏展开,删除注释,包含头文件
    2.编译:语法分析(语法树—>中序遍历),语义分析,词法分析(扫描),代码优化;编译器只编译当前工程的所有源文件,头文件不参与编译(?????),头文件已经展开了。对于当前工程的所有源文件,分别单独编译,分别生成目标文件
 
    1.对模板进行简单的语法检测
    2.生成代码-->前提(实例化)
        未解决的符号表
            编译期间生成未解决的符号表,链接期间进行解决(链接期间到别的已解决的符号表中去找,如果没找到则报错:无法解析的外部符号;如果找到了,则解决了该问题(地址问题))
        已解决的符号表
 

模板的分离编译:
    解决这种问题通过建立全新的"头文件"“.hpp”,相当于将头文件和源文件合并到一块了
推荐方法:
//a.hpp
template<class T,class T>
T& Add(T& left, T& right){
    return left+right;
}
//.cpp
#include"a.hpp"
int main(){
    Add(1,2);
    Add(1.0,3.0);
    return 0;
}
另一种方法(不推荐)
a.cpp:
T& Add(T& left,T& right){
    return left+right;
}
void testFun(){
    这种方法是通过下面代码进行模板的实例化,生成相应的函数,如果不给出实例化,由于每个源文件是单独编译的,因此对于test.cpp源文件中的Add(1,2)会生成未决符号表,在链接期间没有找到相应的函数,所以会报错:无法识别的外部符号
    Add(2,1);
    Add(2.0,1.0);
}
a.h
template<class T,class T>
T& Add(T& left,T& right);
 
test.cpp:
#include"a.h"
int main(){
    Add(2,1);
    Add(2.0,1.0);
    return 0;
}

转载于:https://www.cnblogs.com/love-you1314/p/10367276.html

你可能感兴趣的文章
Apache 启动提示undefined symbol: libiconv_open
查看>>
杨辉三角问题
查看>>
分享27个最新国外超酷单页面网站设计
查看>>
【51CTO学院三周年】写给自己的51cto
查看>>
C++知识体系框图
查看>>
使用cqengine进行集合检索
查看>>
自动化运维Python系列(六)之面向对象
查看>>
LoadRunner测试问题及解决方法总结
查看>>
JAVA学习日记DAY1
查看>>
运动框架
查看>>
用haproxy结合keepalived实现基于LNMP的负载均衡和高可用
查看>>
shell中sed命令的用法
查看>>
Centos Ftp
查看>>
[备忘]几种即见即所得Web编辑器优缺点比较
查看>>
Myeclipse优化设置,加速你的开发武器
查看>>
CentOS 6.5 安装 Mysql 5.7.* (tar.gz)
查看>>
window系统安装redis步骤
查看>>
Linux - Red Hat 7.3 介绍安装
查看>>
linux简单搭建ftp服务器
查看>>
企业管理财务报表:这样做才能小孩子都看得懂!
查看>>