首页 > 编程语言 >C++模板笔记

C++模板笔记

时间:2023-10-18 16:58:38浏览次数:54  
标签:笔记 add 参数 C++ template 默认值 模板 特化

参考文章:https://juejin.cn/post/7078530622527897631

模板是C++的泛型编程机制,这种机制可以最大程度复用代码并且不会增加运行时开销

模板分为函数模板和类模板

函数模板

函数模板是对函数的参数进行泛型化,传递给模板函数的类型实参可以是类,也可以是整型值,还可以是模板名
比如:

// 参数是类型的情况
template<typename T>
T add_1(T a, T b)
{
    return a+b;
}

// 参数是int值的情况
template<typename T, int N>
T add_2(T a, T b)
{
    printf("N=%d\n", N);
    return a+b;
}

// 参数是模板名的情况
template<template<class> class H, typename T>
H<T>& add_h(H<T> a)
{
    return a;
}

函数模板的隐式实例化和显式实例化

显示实例化就是在使用函数模板时指定模板参数
隐式实例化是在使用函数模板时不指定模板参数,让编译器自动推导类型
例如:

add_1<int>(1, 2); // 显式指定了T为int,那就是显式实例化
add_1(1, 2); // 编译器会自动推导T为int,那就是隐式实例化

隐式实例化机制仅针对函数模板而言,类模板中是没有隐式实例化机制的。

类模板

类模板对类的参数进行泛型化,传递给模板类的类型实参可以是类,也可以是整型值
template
class TemplateClass
{
T a;
};

成员函数模板

成员函数也可以用template进行泛型化声明,与前面的函数模板一样。

模板参数可以指定默认值

看到这个地方的时候有个疑问,为什么模板有类型推导机制可以推导出模板的类参数,那为什么还要有默认值的机制?
看到这个例子就明白了:

template <typename T = int>
class DefClass {};

不是所有的模板参数都可以通过模板实参来推导出来。

默认值的指定需要从最右端开始,也就是说从左边开始第一个指定了默认值的参数后,后面的参数都需要指定默认值。
在实例化函数模板时,如果所有参数都有默认值,可以不加<>就可以全部使用默认值,但是对于类模板,必须指定一个空的参数列表<>才能实例化。
另外还要注意,模板默认值功能是从c++0x之后才有,用较老版本的g++编译时需要增加-std=c++0x

参数推导的优先级和默认值的优先级哪个更高

如果一个函数模板的参数既有默认值,并且在实例化时没有指定参数类型,会优先选择哪个类型(默认值还是推导出的类型)?

#include <stdio.h>
#include <typeinfo>

template<typename T1=float, typename T2=float>
void add_3(T1 a, T2 b)
{
    printf("T1 is %s, T2 is %s\n", typeid(T1).name(), typeid(T2).name());
}

经过验证类型推导优先级高一些。

模板参数默认值也可以由前面已定义的typename或者值来得出当前参数的默认值

模板的特化

特化是指在类名或者函数名称后再加一个特定的类型指定,以单独处理需要特别化的情况

函数模板的特化

对于函数模板的特化只能是全特化,不允许偏特化

template<typename T1=float, typename T2=float>
void add_3(T1 a, T2 b)
{
    printf("T1 is %s, T2 is %s\n", typeid(T1).name(), typeid(T2).name());
}

template<>
void add_3<double, double>(double a, double b)
{
    printf("add_3<double, double>, a is %s, b is %s\n", typeid(a).name(), typeid(b).name());
}

add_3(1.1, 1.2);  //add_3<double, double>, a is d, b is d //1.1推导为double,1.2推导为double,所以选择了特化版本的函数模板
add_3(1.1f, 1.2); //T1 is f, T2 is d //1.1f推导为float,1.2推导为double,所以选择了基础版本的函数模板

类模板的特化

全特化

template <>
class Data<char*, char*>
{};

偏特化

部分参数不变,部分参数特化

template <typename T1>
class Data<T1, char*>
{};

参数进一步限制

部分参数进行了限制,比如T*, T&, const T&, const T[], const T[100], const *T[]等

template <typename T1, typename T2>
class Data<T1*, T2*>
{};

优先级是全特化>偏特化>参数进一步限制。

如果参数中有部分特化,另外一部分参数又限制了类型,那此时的优先级是什么样的?

模板参数默认值仅针对基础版本模板可用,特化版本的模板不能定义默认值。

标签:笔记,add,参数,C++,template,默认值,模板,特化
From: https://www.cnblogs.com/lifewithlight/p/17772732.html

相关文章

  • [vue]精宏技术部试用期学习笔记 I
    精宏技术部试用期学习笔记(vue)什么是vue?我个人对vue的理解是把html\css\js三件套融合起来的结构,同时用组件化的思维把一个页面装填起来同时让页面形成树状结构优点是方便多人员维护提高代码复用性如何创建一个vue项目?我这里使用的是vite+vue的轻量化项目,使用pnpm......
  • 基本技巧——分数规划 学习笔记
    基本技巧——分数规划学习笔记引入分数规划用来求一个分式的极值。具体的,给定\(n\)个元素,每个元素有属性\(a_i,b_i\),求一个集合\(P\in[1,n]\),最大/最小化比率:$$\dfrac{\sum_{i\inP}a_i}{\sum_{i\inP}b_i}$$求解二分法假设我们要求最大值(求最小值的方法和求最大值的方......
  • 第四章 文件权限的笔记完善
    第四章 文件权限的相应内容笔记整理1.基本权限UGO使用ll命令来查看文件权限r:read(读取)数字设定为4w: write  (写入)数字设定为2x: execute(执行)数字设定为1owner的权限为“rw”,数字表示6group的权限为“r”,数字表示为4other的权限为“r--",数字表示为4 2.设置......
  • Qt/C/C++ 项目工程架构搭建设计经验
    摘要  独立负责一个Qt项目和经过前辈的教导后的一些架构搭建感悟,其中的各种理念对其他语言开发的项目也能有一定的互通,能带来更舒适的开发体验,谨代表个人开发的经验之谈,有需要的小伙伴酌情获取,辩证思考。也欢迎小伙伴们在评论区纠错补充。  关键词:C/C++、Qt、搭建框架、更......
  • 矩阵求导笔记
    1.标量对矩阵的求导考虑一个标量函数\(f(A)\),其输入是一个\(m\timesn\)矩阵。函数关于矩阵的导数定义为:\[\frac{\partialf}{\partialA}=\begin{bmatrix}\frac{\partialf}{\partialA_{11}}&\cdots&\frac{\partialf}{\partialA_{1n}}\\\vdots&\d......
  • 二分模板
    二分答案的写法有很多模板,但使用的情况各不相同前两种模板:都是while(l<r),但是会有区别的,区别在代码注释中有体现。后两种模板:都是while(l<=r),也是在返回上有区别。这是最大值最小intmain(){ intl; intr; while(l<r) { intmid=(l+r)/2; if(check()......
  • 您需要了解的有关下一个MISRA®标准的信息:MISRA C++ 2023®简介
    我们在直播课中讲解过MISRAC通识及实践(请看VCR),今天我们来探讨一下MISRAC++:2023~ 【北汇信息|MISRAC通识及实践】 MISRAC++:2023®是广受期待的MISRAC++®标准的下一个版本,将于今年晚些时候发布。新版本将整合AUTOSARC++14指南,并支持C++的最新版本。 MISRA®是......
  • Cef笔记:进程间通信
    原文出处:https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage#markdown-header-threadsInter-ProcessCommunication(IPC)SinceCEF3runsinmultipleprocessesitisnecessarytoprovidemechanismsforcommunicatingbetweenthoseprocesses.CefBrowserand......
  • 一点模板
    线性素数筛:欧拉筛:定义数组prim[i]表示第i大的素数,isprim[i]表示i是否为素数(是否被筛过)从2~n遍历,if(!isprim[i])prim[++cnt]=i,如果遍历到i时i仍未被筛,则将i记录于prim数组中。接下来开始以i为基数筛除素数,我们发现:所有的合数都能被筛分割为若干数的积。所以无论i是否为......
  • 【学习笔记】高等代数 2023
    本质上是杂题乱写。最大公约数的辗转相除法首先需要知道良序定理。Well-orderingprinciple(良序定理)我们可以获得一个由自然数组成的集合的最小值来看看良序定理在我们熟知的话题上是怎么应用的如何使用WOP证明\(\sqrt5\)是irrationalnumber?设\(a^2=5b^2\),假设......