C++模板进阶

这篇具有很好参考价值的文章主要介绍了C++模板进阶。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

非类型模板参数

模板参数分为类型模板参数和非类型模板参数;
类型模板参数:就是在模板参数列表中出现在关键字class或typename之后的参数;
非类型模板参数:出现在模板参数列表的整数,该整数是常量,不可更改,可以作为模板的参数来使用;
类模板:C++模板进阶
函数模板:
C++模板进阶
对于类型模板参数来说,我们可以给缺省值,同样的对于非类型模板参数来说,我们也可以给缺省值,模板参数列表的缺省值规则与函数缺省值的规则一样!
C++模板进阶
注意:
1、非类型模板参数必须是整型,不能是浮点数、自定义类型、字符串;
2、那么整型包括那些:int、long int、long long int、char、short等等;、
3、非类型模板参数与#define定义的宏类似,在编译阶段就确定了结果!
非类型模板参数的代表作有STL的容器<array>
C++模板进阶
位图 <bitset>
C++模板进阶\

模板特化

通常情况下,我们可以对某些具体类型,做一些特殊的处理,比如对于一个小于类模板,如果模板正常情况的话,该类就是对于两个元素进行比较,但是如果是两个元素是指针类型的话,我们是不希望用指针的原生值(也就是指针本身)去比较的,我们希望用指针指向的内容来进行比较,因此如果在用原来通用的小于模板的来实例化的话,就不再合适,我们希望对于指针类型能够使用特例话的模板来实例化:
C++模板进阶
我们可以来看看运行结果:
C++模板进阶
我们可以看到结果实在变化的,我们希望是piless(pa,pb)是输出的1,可是为什么它会一会输出0,一会输出1呢?很简单,pliess的模板参数是int*,那么piless<int*>的operator()函数就是判断两个int*指针的大小,由于这指针是我们从堆上new出来的,而且是分开new的,我们无法保证pa先new出来地址就一定比pb后new出来的下,同理也无法保证pa比pb大!因为pa、pb的空间都是随机分配的!
而且,我们本意也不是想比较这两个指针,我们是想让其根据两个指针指向的内容来做小于判断;
那么现在目前这张方法是不行的,是违背我们的初衷的!有没有什么解决办法?
有的!
1、重新写一个模板类,专门用来处理模板参数为指针的:
C++模板进阶
2、我们不需要在重新写一个类模板,我们原来的类模板不是不能对指针类型做出正确的处理嘛,那么我们在利用模板实例化的对象的时候先判断一下模板参数的类型呗!对于指针类型的模板参数我们做一些特殊处理,不用原来的模板实例化,用经过特殊处理的模板来实例化:
C++模板进阶
因此模板特化,就是在原有模板的基础上,根据模板参数做特殊处理的实现方式;
注意实在原有模板的基础上,不可将原有模板删去!原有模板必须存在!
模板分为:函数模板和类模板;同理:模板特化也分为函数模板特化类模板特化

模板特化分类

模板特化呢分为偏特化全特化;
对于类模板来说,它既支持偏特化也支持全特化;
对于函数模板来说,它只支持偏特化;C++语法不支持函数模板的全特化
1、全特化
类模板的全特化;
全特化:就是模板参数的类型都是特定的,比如:现在我有两个模板参数,当T1模板参数为int时,T2模板参数为double时就用当前模板的一个特化模板来实例化对象;
C++模板进阶
运行结果:
C++模板进阶
注意全特化类模板的语法:
还是要写template,只不过模板参数列表里面不用写参数,在类里面也是使用具体类型,注意类名要指名每个模板参数的类型;
2、偏特化
偏特化:也就是对模板参数中的一部分参数做特殊处理,其他参数还是当作泛型!
a、类模板的偏特化
C++模板进阶
注意语法:模板参数列表里面,对那个参数做了特殊处理,那么那个参数就可以不用出现在参数列表,但是后面的类名后面必须出现;
b、函数模板的偏特化:
函数模板的特化步骤:

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

C++模板进阶

模板分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式;
假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:
C++模板进阶
如果我们直接就这样去编译的话,编译是会报错的!准确点来说,在编译阶段没问题,但是在链接的时候会出现问题
C++模板进阶
编译器会告诉我们,它找不到该符号对应的链接;
我们来具体分析一下,编译器到底为什么找不到;
1、我们知道编译器是只会编译源文件的不会编译头文件,头文件在预处理阶段就会被展开在源文件中!那么现在我们有两个源文件:a.cpp、main.cpp;
编译器就会对这两个源文件进行编译,在此期间两个源文件的编译都是分离的独立的进行的互不干扰的!
C++模板进阶
以上的事情都是编译器做的!那么在做完这一切过后,如果我们想要得到一个可执行文件的话,那么链接器就要发挥作用了,那么链接器是如何发挥作用的呢?
首先在汇编阶段,每个源文件都会形成符号表!什么是符号表呢?
符号表就是当前源文件对于出现在当前文件的一些符号的统计,并且为这些符号建立链接关系(也就是为这些符号映射一个地址!),这些符号包括哪些?
全局变量、静态遍历、函数名等:
C++模板进阶

解决办法

  1. 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。
  2. 模板定义的位置显式实例化。这种方法不实用,不推荐使用。
    C++模板进阶

模板总结

【优点】文章来源地址https://www.toymoban.com/news/detail-401014.html

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性
    【缺陷】
  3. 模板会导致代码膨胀问题,也会导致编译时间变长
  4. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

到了这里,关于C++模板进阶的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶(十)】C++模板(进阶) ---非类型模板参数、模板的特化以及模板的分离编译

    本专栏内容为:C++学习专栏,分为初阶和进阶两部分。 通过本专栏的深入学习,你可以了解并掌握C++。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:C++ 🚚代码仓库:小小unicorn的代码仓库🚚 🌹🌹🌹关注我带你学习编程知识 模板参数可分为类型形参和非类型形参。 类型形

    2024年01月18日
    浏览(38)
  • C++函数模板、特例化、非类型参数、类模板、allocator

    模板对类型能进行参数化成【模板参数】,输入的是类型,生成的是代码。使用的时候,每指定一份类型,模板就会根据类型生成一份新的代码(比如函数模板实例化生成的是【模板函数】),有利于减少代码量,通过较少的代码也能实现函数重载。 调用函数模板的时候,一

    2024年02月21日
    浏览(44)
  • 【C++进阶】C++11(下)可变参数模板&lambda表达式&包装器

    我们紧接着上一节的讲解来进行 C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象,使用起来需要一定的技巧

    2024年04月11日
    浏览(90)
  • 非类型模板参数

    背景 除了日常用的typename以外,模板还有很多非类型模板参数 具体 int 或者 enums 对象指针和函数指针(好像很多编译器都支持void*) 左值引用(用的不多) 模板模板类型 模板模板类型 其他都比较常见且容易理解,重点看看这个: Base前面的typename在C++11之前必须是class,C++11以后才

    2024年02月15日
    浏览(34)
  • C++17完整导引-模板特性之占位符类型模板参数

    自从 C++17 起,你可以使用占位符类型( auto 和 decltype(auto) )作为 非类型模板参数的类型 。这意味着我们可以写出泛型代码来处理不同类型的非类型模板参数。 自从 C++17 起,你可以使用 auto 来声明非类型模板参数。例如: 这允许我们为不同类型实例化非类型模板参数 N :

    2024年02月06日
    浏览(33)
  • 【C++进阶】模板进阶

    👦个人主页:@Weraphael ✍🏻作者简介:目前学习C++和算法 ✈️专栏:C++航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨ 初阶模板地址:点击跳转 在以前博客我们说过,定义模板参数可以用 typename ,

    2024年02月10日
    浏览(30)
  • C++模板的模板参数(五)

    在C++中,模板的模板参数(Template Template Parameters)是一种特殊的模板参数,允许我们将另一个模板作为模板参数传递给一个模板。这种技术可以用于实现更灵活和通用的模板设计。 模板的模板参数使用两个 “template” 来指示,其中第一个 “template” 用于声明模板参数

    2024年02月10日
    浏览(36)
  • 【C++】模板进阶|继承

    模板参数 分为 类型形参 和 非类型形参 类型形参 即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参 ,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。 这里我们引入一个例子来说明问题: 这里有

    2023年04月08日
    浏览(40)
  • C++之模板进阶

    模板参数分两种: 类型形参 与 非类型形参 。 类型形参 :出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参 :就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。 注意 : 浮点数、类对象以及字符串是不

    2024年02月12日
    浏览(26)
  • C++模板进阶

    模板参数分为类型模板参数和非类型模板参数; 类型模板参数:就是在模板参数列表中出现在class或typename之后的参数; 非类型模板参数:出现在模板参数列表的整数,该整数是常量,不可更改,可以作为模板的参数来使用; 类模板: 函数模板: 对于类型模板参数来说

    2023年04月08日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包