首页 > 其他分享 >16理解函数模板

16理解函数模板

时间:2024-01-16 10:57:46浏览次数:28  
标签:compare 函数 16 特例 参数 类型 模板

理解函数模板

模板的意义:对函数类型可以做修改

  • 函数模板:bool compare(T a, T b)
  • 模板实例化:定义一个模板参数类型,进行一次函数的实例化
  • 模板函数:一个函数模板的实例化就是一个模板函数
  • 模板类型参数:T
  • 模板非类型参数:
  • 模板的实参推演:根据实参反推模板参数类型
  • 模板的特例化:为函数模板的特殊参数类型进行特殊设置
  • 对于某些类型来说,依赖模板的函数逻辑是有问题的。需要模板的特例化,特例化不是编译器提供的,而是用户提供的一种实例化方法,
  • 函数模板 模板的特例化 非模板(普通)函数的重载关系:如下例三个字符串的compare函数,一般优先调用非模板函数,如果非模板函数不存在,才会调用特例化模板函数或模板函数。
#include <iostream>
#include <cstring>
using namespace std;

template<typename T> //定义一个模板类型参数列表,也可以定义为类
bool compare(T a, T b) { //compare是一个函数模板
	cout << "template" << endl;
	return a > b;
}
template<> //模板的特例化:针对compare函数模板,提供一个给const char*的特例化版本
bool compare(const char *a, const char *b) { //compare是一个函数模板
	cout << "str template" << endl;
	return strcmp(a, b) > 0;
}
//compare是一个函数模板
//在函数调用点,编译器用用户指定的类型,从原模版实例化一份函数代码
//从函数模板实例化出来的函数为模板函数,如下
//符号表会依据函数名和参数类型为每个模板函数加入新符号,模板函数才是真正被编译的函数,而函数模板不是
//bool compare<int>(int a, int b) { 
//	cout << "template" << endl;
//	return a > b;
//}
//bool compare<double>(double a, double b) { 
//	cout << "template" << endl;
//	return a > b;
//}

int main() {
	//函数的调用点
	compare<int>(10, 20);
	compare<double>(10.0, 20.0);
	compare(10, 20); //函数模板的实参推演:根据用户传入的实参类型,反推出模板所使用的类型参数
	//第二次使用compare<int>时不需要再次产生模板函数,直接调用第一次产生的函数即可
	//compare(10, 20.0); //报错,无法确定模板参数类型
    compare("aa", "bb"); //可以执行,默认实参自动推演为const char*,从而比较两个指针地址的大小。
    //如果进行字符串的字典比较,如何?
	return 0;
}
  • 如果将函数模板定义在另一个文件中定义,会出现问题。因为模板本身不会编译,模板函数才会编译。如果A文件中调用了B文件中的模板函数,事实上在编译汇编阶段,B文件并不会编译产生A所需的模板函数,符号表中也不会产生对应符号,因此在链接阶段,A文件所需使用的几个*UND*函数符号无法在B中找到。不过,B中定义的普通函数和特例化模板函数在A中是可以被看到的。因此模板源代码一般都放在头文件中,在源文件中#include直接展开。
  • 如果在调用之前,声明函数模板对应类型的模板函数,也可以避免上述情况,一般不这样。

标签:compare,函数,16,特例,参数,类型,模板
From: https://www.cnblogs.com/sio2zyh/p/17967130

相关文章

  • 10构造函数与析构函数
    构造函数和析构函数#include<iostream>usingnamespacestd;classseqStack{private: int*_pstack; int_size; int_top;public: seqStack(intsize){ _size=size; _pstack=newint[size]; _top=-1; } ~seqStack(){ delete[]_pstack; _pstack......
  • 算法模板 v1.1.1
    算法模板编译CF模板#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/typedeflonglonglnt;/*====================*/voidSolve(void){}/*====================*/intmain(){#ifn......
  • python网站创建016:BootStrap
    什么是BootStrap?:是一个别人写好的javascript和css的代码,如果在开发项目的时候省点事,就可以在它的基础上来修改使用使用教程:https://www.runoob.com/bootstrap/bootstrap-tutorial.html下载:https://getbootstrap.net/   下载之后解压,解压之后可以随意打开一个文件,比如cs......
  • 割函数是子模函数
    然而Ishy并不会证这个标题。但是Ishy会证那个最具标志性的不等式。记\(\mathrm{cut}(A)\)表示点集\(A\)与其在流网络上的补集的切割值,\(\mathrm{cut}(A,B)\)表示点集\(A\)向\(B\)的广义切割值(即起点在\(A\)、终点在\(B\)的边权和)。记\(A/B\)表示\(A\)中......
  • mysql 中 utf8、utf16、utf32、utf8mb3、utf8mb4的区别
    UTF-8-“大小优化”:最适合基于拉丁字符的数据(或ASCII),每个字符只需1个字节,但大小相应增加符号种类(在最坏的情况下,每个字符最多可增加6个字节)UTF-16-“平衡”:每个字符至少需要2个字节,足以支持现有的主流语言集,并且具有固定的大小以便于字符处理(但是大小仍然可变,每个字符最多......
  • 1.8 - 高阶函数与递归函数
    1.8.1高阶函数高阶函数:其形参或返回值为函数。#filter(function,iterable)#将可迭代对象中的元素依次作为实参传递给指定的形参函数function调用,返回新的可迭代对象tup=(1,2,0,False,True,-1)obj=filter(lambdax:x-1,tup)print(list(obj))#[2,......
  • vue中render函数和h函数
    "render"函数是Vue组件的一个重要方法,它用于描述组件的视图结构,并负责渲染虚拟DOM树。"render"函数是一个JavaScript函数,它接受一个名为createElement的参数,用于创建虚拟DOM节点。这使得你可以使用JavaScript来构建虚拟DOM树,包括元素、组件、指令等,为你提供更高的灵活性。render......
  • C# 对两个需要顺序执行的函数进行异步交叉,提高执行速度
    有的时候我们会有2个函数需要顺序执行,比如将数据库的数据写到硬盘上,读数据库和写硬盘都是IO比较慢的操作,于是我们很容易就想到让他们异步执行,避免阻塞,提高性能,但是为了保证数据的顺序一致,我们又需要整个队列来存放数据,感觉比较麻烦,今天研究了下,通过异步和信号量控制实现了两个函......
  • thymeleaf—02—模板
    一、th:fragment模板片段我们可以使用模板,定义一些会经常复用的代码,使用th:fragment定义然后使用th:insert引入这个模板内容,或者使用th:replace进行内容替换;还有一个th:include标签也是引入模板内容,但是这个不推荐了; 除了增加模板,还可以使用th:remove进行模板的删除操作; ......
  • 函数参数传递方式
    两种传递方式:值传递:基本数据类型int系列,float系列,bool,string,数组,结构体struct。(值类型)引用传递:指针,slice切片,map,chan管道,interface等都是引用传递。(引用类型)其实不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是,值传递的是值的拷贝,引用传递的是地......