C++:模板的特化与分离编译

news2024/10/24 20:32:33

之前我们在介绍模板的时候仅仅是简单的介绍了模板的用法,本篇文章我们来详细的介绍下模板中比较重要的几个点。

一,非类型模板参数

我们之前的c中,会将经常使用的而又确保在我们程序的运行过程中值不会改变的值进行#define:

#define N 10

但是如果我们在不同的类中如果都有这样的一个值,显然我们去定义这样的一个值是完全不够我们使用的,这时候就需要我们的非类型模板参数来解决这种问题:

template<class T,size_t N = 10>
//第一个是类型模板参数,第二个是非类型模板参数
//可以不给非类型模板参数缺省值

TIPS:

1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。(C++20及更高版本才支持)
2. 非类型的模板参数必须在编译期就能确认结果

二,模板的特化 

2.1概念 

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些
错误的结果,需要特殊处理。比如我们有这样一个进行比较的模板参数:

template<class T>
bool Less(T left, T right)
{
    return left < right;
}

我们直接传值当然会得到我们想要的结果,但是如果我们传入的是T类型的指针,比较的便是指针地址的大小。这没有意义,如果我们还想要去对其指向的数据进行比较,就需要使用模板的特化:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化与类模板特化。(函数模板的特化我们只是介绍,因为这种情况下我们一般需要在去写一个这样的比较函数,下面对函数模板的介绍我们只需要了解即可,主要的是类模板的特化)。

2.2函数模板的特化

函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同(就是源模板的T是int类型,你特化后的参数必须是int类型的指针,引用等),如果不同编译器可能会报一些奇
怪的错误。

// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
    return left < right;
}
// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
    return *left < *right;
}

注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该
函数直接给出。
 所以一般我们不建议使用函数模板的特化。

2.3类模板的特化 

2.3.1全特化

我们先来看全特化的一个例子:

(全特化即是将模板参数列表中所有的参数都确定化)

template<class T1, class T2>
class Data
{
public:
    Data() {cout<<"Data<T1, T2>" <<endl;}
private:
T1 _d1;
T2 _d2;
};
template<>
class Data<int, char>
{
public:
    Data() {cout<<"Data<int, char>" <<endl;}
private:
int _d1;
char _d2;
};

2.3.2偏特化 

再来看下偏特化:(任何针对模版参数进一步进行条件限制设计的特化版本) 

第一种是将部分参数确定化:

template <class T1>
class Data<T1, int>
{
public:
    Data() {cout<<"Data<T1, int>" <<endl;}
private:
T1 _d1;
int _d2;
};

对于特化的匹配规则是,比如下面这样一个例子:

template<class T1, class T2>
class fun1
{
public:
    fun1()
    {
        cout << 1 << endl;
    }
private:
    T1 _t1;
    T2 _t2;
};

template<class T1>
class fun1<T1, int>
{
public:
    fun1()
    {
        cout << 2 << endl;
    }
private:
    T1 _t1;
    int _t2;
};

template<>
class fun1<char, int>
{
public:
    fun1()
    {
        cout << 3 << endl;
    }
private:
    char _t1;
    int _t2;
};

template<class T2>
class fun1<int, T2>
{
public:
    fun1()
    {
        cout << 4 << endl;
    }
private:
    int _t1;
    T2 _t2;
};

int main()
{
    fun1<char, int> a;//3
    fun1<size_t,int> b;//2
    fun1<int, size_t> c;//4
    fun1<size_t, size_t> d;//1
    return 0;
}

也就是说,能完全匹配则取最符合的那个。第二个位置为int就去调用第二个位置为int的特化,第一个位置为int调用第一个位置为int的特化。注意,此时我们如果输入<int,int>会报错,因为这既符合我们的第二种又符合我们的第三种,此时需要删除一种。 

第二种则是参数更进一步的限制:

//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
    Data() {cout<<"Data<T1*, T2*>" <<endl;}
private:
    T1 _d1;
    T2 _d2;
};

//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:
Data(const T1& d1, const T2& d2)
    : _d1(d1)
    , _d2(d2)
{
    cout<<"Data<T1&, T2&>" <<endl;
}
private:
    const T1 & _d1;
    const T2 & _d2;
};

当然也可以混到一起,比如我第一个位置是引用,第二个位置是指针。或者反过来。 

三,模板的分离编译

3.1分离编译的概念

 一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有
目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

3.2模板的分离编译 

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

// a.h
template<class T>
T Add(const T& left, const T& right);

// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}

// main.cpp
#include"a.h"
int main()
{
    Add(1, 2);
    Add(1.0, 2.0);
    return 0;
}

 分析:

所以一般情况下,我们的模板的定义和声明是不分离到两个文件中的。但是需要注意,这并不是一种语法错误,而是一种链接错误。不久的将来,编译器有望支持export关键字,实现模板分离编译。 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity Apple Vision Pro 保姆级开发教程-环境配置、导入 PolySpatial 案例、程序发布到设备

视频教程 Unity 环境配置、导入 PolySpatial 案例、程序发布到设备 Unity Vision Pro 中文课堂教程地址&#xff1a; Unity3D Vision Pro 开发教程【保姆级】 | Unity 中文课堂 教程说明 这期教程我将介绍使用 Unity 开发 Apple Vision Pro 应用所需要的 Unity 环境配置&…

055_基于python摄影平台交流系统

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

Android compose 重建流程1

前言 本文是笔者学习Compose是如何自动触发UI刷新的笔记,可能缺乏一定可读性和教导性.(建议阅读参考文献更具启发性) 使用以下BOM作为研究环境. composeBom "2024.04.01" androidx-compose-bom { group "androidx.compose", name "compose-bom…

实习冲刺Day2

算法题 反转链表 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}*…

AI大模型应用(3)开源框架Vanna: 利用RAG方法做Text2SQL任务

AI大模型应用(3)开源框架Vanna: 利用RAG方法做Text2SQL任务 RAG&#xff08;Retrieval-Augmented Generation&#xff0c;如下图所示&#xff09;检索增强生成&#xff0c;即大模型LLM在回答问题时&#xff0c;会先从大量的文档中检索出相关信息&#xff0c;然后基于这些检索出…

【LLaMA-Facrory】【模型评估】:代码能力评估——Qwen-Coder-7B 和 deepseek-coder-7b-base-v1.5

目录 序言 1 拉取 Qwen2.5-Coder-7B 模型 2 编写python测试模型 3 启动webui导入模型测试 4 模型评估 4.1 前期准备工作 4.2 Qwen2.5-Coder-7B 模型评估 数据说明 综合分析 4.3 deepseek-coder-7b-base-v1.5 模型评估 数据说明 综合分析 4.4 模型比较 1. 文本生成…

软件安全测试报告如何编写?CMA、CNAS软件安全测试机构推荐

随着软件产品的增多&#xff0c;产品安全成为软件企业留住用户的方法之一。安全测试是验证和检查软件安全的重要手段&#xff0c;而软件安全测试报告则是测试人员工作成果的最好体现&#xff0c;那么软件安全测试报告该如何编写呢?权威的CMA、CNAS软件安全测试机构又有哪些? …

WeMapEngine开发实战,创建你的第一个GIS项目

我们在《WeMapEngine可快速构建的GIS应用功能》一文中为你分享了WeMapEngine可快速建的GIS应用功能。 今天再为你分享基于WeMapEngine的开发实战&#xff0c;演示如何快速创建第一个GIS项目。 创建你的第一个GIS项目 现在&#xff0c;我们开始构建第一个项目。 在这个项目中…

emulator -version报错解决方案

使用android studio安装安卓环境之后&#xff0c;会发现emulator -version报如下错 [14960]:ERROR:android/android-emu/android/qt/qt_setup.cpp:28:Qt library not found at ..\emulator\lib64\qt\lib Could not launch C:\Users\litbai\..\emulator\qemu\windows-x86_64\qe…

【Java小白图文教程】-04-循环结构

精品专题&#xff1a; 01.《C语言从不挂科到高绩点》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482 02. 《SpringBoot详细教程》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12789841.html?spm1001.20…

深入理解计算机系统--计算机系统漫游

对于一段最基础代码的文件hello.c&#xff0c;解释程序的运行 #include <stdio.h>int main() {printf ( "Hello, world\n") ;return 0; }1.1、信息就是位上下文 源程序是由值 0 和 1 组成的位&#xff08;比特&#xff09;序列&#xff0c;8 个位被组织成一组…

springboot048校园资料分享平台(论文+源码)_kaic

校园资料分享平台 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了校园资料分享平台的开发全过程。通过分析企业对于校园资料分享平台的需求&#xff0c;创建了一个计算机管理校园…

无人机的电池放电详解!

一、定义与表示方法 无人机的电池放电率是指电池在一定时间内放出其储存电能的能力&#xff0c;这一参数通常用C数来表示。C数越大&#xff0c;表示放电速率越快。 例如&#xff0c;一个2C的电池可以在1/2小时内放完其全部电量&#xff0c;而一个10C的电池则可以在1/10小时内…

喜讯!望繁信科技荣膺2022年中国超自动化先锋企业TOP20

36氪重磅发布「2022中国超自动化先锋企业」调研结果。凭借多年在流程挖掘领域过硬的技术实力和突出的产品创新力&#xff0c;望繁信科技在众多调研样本企业中脱颖而出&#xff0c;赢得了专家评委的充分认可&#xff0c;成功入选2022年中国超自动化先锋企业TOP20。 什么是超自动…

【书生大模型实战营】闯关任务1-入关岛

这里写自定义目录标题 第一关 L0G1000 Linux 基础知识 第一关 L0G1000 Linux 基础知识 SSH连接与端口映射并运行hello_world.py 关键截图&#xff1a;

502 错误码通常出现在什么场景?

服务器过载场景 高流量访问&#xff1a;当网站遇到突发的高流量情况&#xff0c;如热门产品促销活动、新闻热点事件导致网站访问量激增时&#xff0c;服务器可能会因承受过多请求而无法及时响应。例如&#xff0c;电商平台在 “双十一” 等购物节期间&#xff0c;大量用户同时…

Windows解决localhost拒绝了连接请求

最近&#xff0c;在开发前端Vue项目时&#xff0c;Vue项目启动成功&#xff0c;没有任何报错&#xff0c;服务控制台已出现APP访问地址&#xff0c;如下图所示。 览器打开后页面先是空白&#xff0c;然后过了一会儿显示无法访问此网站&#xff0c;localhost拒绝了我们的连接请…

WPF MVVM模式实现DataGrid编辑

本文是一个MVVM模式开发的基础教程&#xff0c;完全手写实现&#xff0c;未借助三方框架&#xff0c;适用于初学者 要实现DataGrid的编辑&#xff0c;步骤如下&#xff1a; 1、创建两个窗口&#xff0c;第一个窗口用于显示DataGrid&#xff0c; 布局如下&#xff1a; 这个界…

Data+AI下的云数仓未来已来!

DataAI下的云数仓未来已来&#xff01; 前言云数仓是什么&#xff1f;云数仓的概念与背景数据孤岛问题与云数仓的优势 现代数仓如何建设&#xff1f;灵活架构与弹性扩展实时与离线处理并存安全与合规性&#xff1a;现代数仓的基石 AI如何助力数仓建设&#xff1f;AI驱动的数据处…

《探索 NESMA:软件度量领域的璀璨之星》

《探索 NESMA&#xff1a;软件度量领域的璀璨之星》 一、NESMA 初印象 NESMA&#xff08;Netherland Software Measurement Association&#xff09;&#xff0c;作为荷兰软件度量协会的简称&#xff0c;在软件规模度量领域占据着重要地位。它是五种 ISO 国际功能点标准之一&am…