首页 > 编程语言 >C++泛型一:模板

C++泛型一:模板

时间:2024-10-31 17:36:05浏览次数:1  
标签:auto C++ 类型 参数 template 泛型 模板

数据类型给程序设计带来的困扰及解决方案

int maxt(int, int);
double maxt(double, double);

若有一种占位符T,能够代替类型,便可以简化代码的冗余编写

T maxt(T,T);

C++模板

模板声明如下

template<typename T1, ...>

template是C++的模板声明关键字,尖括号内为模板参数列表
typename为类型占位符声明关键字

template<typename T>
T maxt(T x, T y){
    return (x>y)? x: y;
}

函数模板

预编译阶段,当程序中调用函数模板时,编译器会用实际类型替换类型占位符生成实体函数
若编译器可以从函数实参中推导出模板参数所需类型,则可以不传入模板参数

template<typename T>
T maxt(T x, T y){
    return (x>y)?x:y;
}

int main(int argc, char* argv[]){
    // std::cout<< maxt<int>(4,6)<< std::endl;
    std::cout<< maxt(4,6)<< std::endl;

    return 0;
}

类模板

在声明类时,使用template进行模板声明即可

template<typename T>
class Circle{
public:
    Circle(T r);
}

若在类模板外实现成员函数,则必须声明为函数模板

template<typename T>
Circle<T>::Circle(T r){}

在调用时,需要在类名后使用尖括号传递具体类型

Circle<int> circle;

STL的模板编程对面向对象技术并不感兴趣,其认为类对数据的过度封装影响程序的执行效率
而为了更好的管理代码,所以STL中使用大量没有访问权限的struct制作的类模板

变量模板

变量模板,将模板扩展到变量
pi<T>的实现
Tdouble时,返回3.14
Tint时,返回3
Tstring时,返回"3.14""pi"

C++新标准对泛型设计的努力

auto和decltype

C++11中,auto关键字,用来推导变量的数据类型auto a=100;
auto类型的获取可通过编译器的类型记忆能力或decltype的类型提示来推导

利用类型记忆推导复杂类型

auto目前能力有限,只对系统的内置数据类型有效
对于用户自定义类型或复杂类型,只有当编译器取得足够经验后,才具备推导能力

map<int,map<int,int>>::const_iterator iter1=map1.begin();
auto iter2=map1.begin();

由于前一条语句告知了编译器map1.begin()的类型,在处理第二条语句时,便利用了记忆能力自动推导出iter2的类型

decltype表达式对推导函数返回值类型进行指导

变量类型难以确定的问题一般出现在函数返回值上,C++11可以使用decltype对函数返回值的类型推导工作进行指导
当返回auto类型,需要编译器对函数返回值类型进行推导时,可用decltype对该推导工作进行指导

template<typename T, typename U>
auto Multiply(T t, U u)->decltype(t*u){
    return t*u;
}

这种使用auto作为函数返回值类型的称为auto返回值占位

auto看作数据类型,则auto也是一种泛型,只不过无须关键字typename声明
且实际类型不是由实参显式提供,而是根据类型操作相关历史记忆及应用程序提供的推导思路

模板参数

根据参数实参的性质,模板参数分为类型参数,非类型参数和模板定义型参数三种

类型参数

用关键字typename声明的参数
类型参数的类型实参包括:

  • 系统内置的类型
  • 用户自定义的数据类型
  • 编译器刚学到的类模板实体
  • typename定义的类型别名

非类型参数

C++允许在模板参数列表中定义普通变量或对象,如template<typename T, int a>
由于模板参数是在预编译阶段进行传递并被编译的,故这种非类型参数在模板代码内是常量,不能修改
对于这种参数,目前C++仅支持整型int(或可转为int的类型,如bool),枚举,指针和引用类型

C++11支持非类型参数在定义时赋值,如template<typename T, int b=100>

模板定义型参数

以类模板作为类模板参数,除了强调这个类型参数必须为类模板外,还强调该类模板的参数个数

// 单模板参数的类模板
template<typename T>
struct S_Tmp{};

// 多模板参数的类模板
template<typename T, typename R>
struct D_Tmp{};

// 以单参数类模板作为参数的类模板
template<template<typename S>class T>
struct MyTest{};

int main(){
  MyTest<S_Tmp> tt1;
//   MyTest<D_Tmp> tt1; // error
  return 0;
}

模板形参和实参的结合

函数模板实参的隐式结合

编译器可以根据函数实参类型推导出模板形参所对应的实参,这种在调用函数模板时可以省略模板参数列表
由于函数调用语句中不提供函数返回值的类型信息,所以模板的返回值类型占位符必须与某个形参的占位符相同

指针实参

C++中,指针是一种数据类型,因此可作为模板实参

修饰字const和&的使用

可以在模板调用参数列表中使用修饰字const&

template<typename T1, typename T2>
const T1& add(const T1& a, const T2& b){
    return a;
}

模板特例化与模板具现

模板特例化

数据类型的变化通常与业务逻辑无关
若有个别数据类型所对应的算法与其他类型对应的算法不同,这类算法就要单独编写

函数模板的特化

如判断大小的函数,数值类型与字符串类型的比较算法是不一样的,应该分开实现

template<typename T>
T mymax(T a, T b){
    return a>b?a:b;
}
template<>
char* mymax(char* a, char* b){
    return (strcmp(a,b)<0)?b:a;
}

使用template<>是为了将其纳入maxt模板体系

类模板的特化与偏特化

// 普通模板
template<typename T1, typename T2>
struct Test{};

// 偏特化模板
template<typename T>
struct Test<int, T>{};

// 全特化模板
template<>
struct Test<int, float>{};

模板的具现

编译器在匹配模板生成实体代码时的优先级

  1. 特化模板(函数或类)
  2. 偏特化模板(类)
  3. 普通模板(函数或类)

标签:auto,C++,类型,参数,template,泛型,模板
From: https://www.cnblogs.com/sgqmax/p/18518481

相关文章

  • C++范型二:右值引用
    为类所设计的转移语义拷贝构造函数和转移语义赋值运算符使得临时对象有了将资源直接转移给另一个对象的能力,从而避免了内存分配、资源拷贝等深拷贝过程作为注重效率的模板,当然要引入右值引用及相关技术,其成果就是参数完美转发模板右值引用左值和右值左值代表一块存储空间,可以......
  • C++范型三:数据类型表
    类的数据类型成员C++中,在类模板中用typedef定义的数据类型称为内嵌类型nestedtypetemplate<typenameT>classMyTraits{public:typedefTmytype;};如下,使用内嵌类型在类外定义变量typenameMyTraits<int>::mytypen;可知,类外引用类模板的公有类型成员和引用类静......
  • C/C++中的指针详解(重点)
    指针是C和C++中一个重要且强大的特性。它们允许程序员直接访问和操作内存,提供了灵活的内存管理和高效的数据结构实现。对一个变量取*操作其实就是取到这个变量的地址,然后再对取到的变量进行读写等操作以下是对指针的详细介绍:1.什么是指针指针是一个变量,它存储另一个变量的......
  • 【C++】01-C++ 程序的生成过程
    概要:该篇文章以MSCV为例,简要介绍了C++程序的生成过程。1.生成工具MSVC,全称MicrosoftVisualC++,是由微软开发的用于生成C++程序的工具集,包括C++预处理器、编译器、链接器和其他生成工具。2.生成过程2.1预处理(Preprocess)预处理由预处理器(Preprocessor)......
  • C++ halcon判断图像是否为空
    使用CountObj函数首先,可以使用CountObj函数来检查当前图像是否为空。如果图像为空,则返回的计数为0;否则,返回的计数大于0。示例代码如下:cppCopyCode HTuplehNum;HalconCpp::CountObj(m_hCurrentImg,&hNum);if(hNum==0){qDebug()<<"传入图像为空!";}else{qDebu......
  • 界面控件Kendo UI for Angular 2024 Q3亮点 - 全新的页面模板
    随着最新的2024Q3版本,Progress使用户能够使用现成的页面模板和构建块更快地构建令人惊叹的应用程序,使您的Telerik和KendoUI开发体验更好。Telerik和KendoUI 2024Q3版本将焦点放在新推出的页面模板和构建块上,每个页面模板和构建块都预先配置了TelerikUIforBlazor、KendoU......
  • 【C++】红黑树的插入与删除
    第一篇数据结构学习之红黑树的实现系列文章目录前言一、红黑树的基本概念二、参考视频链接三、代码实现1.定义节点类2.旋转方法3.红黑树插入操作4.红黑树删除操作四,总体代码总结系列文章目录第一篇数据结构学习之红黑树的实现前言红黑树是一种平衡二叉搜索树,在......
  • C++——写一函数,将一个3x3的整型矩阵转置。用指针或引用方法处理。
    没注释的源代码#include<iostream>usingnamespacestd;voidmove(int*p);intmain(){  inta[3][3],*p;  cout<<"pleaseinputmatrix:"<<endl;  for(inti=0;i<3;i++)  {    for(intj=0;j<3;j++)    {     ......
  • C++——将一个5x5的矩阵中最大的元素放在中心,4个角分别放4个最小的元素(按从左到右、
    没注释的源代码#include<iostream>#include<stdio.h>#include<string.h>usingnamespacestd;voidtransform(int*arry,intcol_row);intmain(){   intarry[5][5];   cout<<"Pleaseentera5x5matrix:"<<endl;   for(......
  • 管家婆工贸ERP BB067.销售订单修改BOM类型+BB068.销售单按模板导出Excel
    BB067.销售订单修改BOM类型最低适用版本:工贸系列23.0插件简要功能说明:销售订单任意状态下,支持通过应用按钮将焦点行的BOM类型修改为订单BOM更多细节描述见下方详细文档插件操作视频:进销存类定制插件--销售订单修改BOM类型插件详细功能文档:销售订单增加应......