模版进阶篇章

server/2024/9/24 8:37:18/

非类型模版参数

回顾:函数模版 :不用传类型,编译器会自动推导,和普通的函数调用一样

#include<iostream>
using namespace std;
template<typename T>// T是类型
bool Less(T a, T b)// a,b是T实例化的的对象
{return a < b;
}
int main()
{cout << Less<int>(1,2) << endl;cout << Less(1, 2) << endl;return 0;
}

类模版:通过传不同的类型,编译器会自动生成不同的类,然后进行实例化对象

namespace bit
{template<typename T>// T是类型class array{array( int size = 1 ){_array = new T[size];_size = size;}bool empty(){return _size == 0;}int size(){return _size;}private:T* _array;int _size;};
}

注意:调用函数模版时,需要传对象(匿名实例化 或者 有名实例化)         

           调用类模版时,需要传类型

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
int main()
{
//函数模版vector<int> s = { 1, 2, 4, 6, 7,3,1 };sort(s.begin(), s.end(), less<int>());//升序for (auto& e : s)cout << e << " ";cout << endl;sort(s.begin(), s.end(), greater<int>());//降序for (auto& e : s)cout << e << " ";cout << endl;
//类模版priority_queue<int, vector<int>, less<int>> k;// 传的是类型k.push(1);k.push(3);k.push(9);k.push(10);while (!k.empty()){cout << k.top() << " ";k.pop();}cout << endl;return 0;
}

非类型模版参数

概念:将常量作为模版参数

注意:1.只有整形家族才能支持非类型模版参数

           2.参数在编译时就能确定

#include<iostream>
#include<algorithm>
using namespace std;
namespace bit
{template<typename T ,size_t size = 10>class array//静态数组{public:array( ){_array = new T[size];_size = size;}bool empty(){return _size == 0;}int size(){return _size;}private:T* _array;int _size;};
}
int main()
{bit::array<int, 20> s;return 0;
}

模版参数可以支持缺省参数(类似于函数)

在priority_queue中我们以vector作为priority_queue的底层(参考我的另一篇文章:详细的讲解priority_queuede的用法与底层https://blog.csdn.net/wx20041102/article/details/138355281?spm=1001.2014.3001.5501)

模版特化

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错

误的结果

列如:

#include<iostream>
#include<deque>
#include<algorithm>
#include<vector>template<typename T>
class Less
{
public:bool operator() (const T& x, const T& y){return x < y;}
};template<typename T>
class Greater
{
public:bool operator() (const T& x, const T& y){return y < x;}
};class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& s){if (s._year > _year)return true;else if (s._year == _year){if (s._month > _month)return true;else if (s._month == _month){if (s._day > _day)return true;}}return false;}
private:int _year;int _month;int _day;
};
int main()
{Date* p1 = new Date(2024, 1, 1);Date* p2 = new Date(2024, 1, 4);Less<Date*> ls;cout << ls(p1 , p2) << endl;//这里比较的是地址大小,而我们想要比较指向的内容大小return 0;
}

解决方案:特化

  • 函数模版特化

步骤如下:

1.必须要有一个基础的函数模版

2.关键字template后接一对空的<>

3.直接在()中写出要特化的类型

4.函数形参表:必须要和模版参数的基础类型完全相同

#include<iostream>
#include<vector>
using namespace std;template<typename T>
bool Less(T& x, T& y)
{return x < y;
}template<typename T>
bool Less(int*& x, int*& y)
{return *x < *y;
}template<typename T>
bool Less(string*& x, string*& y)
{return *x < *y;
}
int main()
{int* p1 = new int(1);int* p2 = new int(3);cout << Less<int*>(p1, p2) << endl;return 0;
}

既然参数类型已经确定,那么函数模版也可以用函数重载(这是我们经常用的)

#include<iostream>
#include<vector>
using namespace std;template<typename T>
bool Less(T& x, T& y)
{return x < y;
}bool Less(int*& x, int*& y)
{return *x < *y;
}bool Less(string*& x, string*& y)
{return *x < *y;
}
int main()
{int* p1 = new int(1);int* p2 = new int(3);cout << Less<int*>(p1, p2) << endl;return 0;
}
  • 类模版特化

  • 全特化

类型全部确定

步骤如下:

1.template 后接一对<>

2.class 类型名 + < 类型 >//注意这里要将类模版中全部的参数写出来

#include<iostream>
#include<algorithm>
using namespace std;
template<typename T , typename K>
class date
{
public:date(){cout << "111111111" << endl;}
private:T _a;K _b;
};
template<>
class date<int,char>
{
public:date(){cout << "22222222222" << endl;}
private:int _a;char _b;
};int main()
{date<int, char> s;date<char, char> k;date<int, int> q;
}
  • 偏特化
部分特化

1.template< 需要实例化的类型 >//template<typename T>

2.class <需要实例化的类型 + 缺省类型 >// class < T , char >

#include<iostream>
#include<algorithm>
using namespace std;
template<typename T , typename K>
class date
{
public:date(){cout << "111111111" << endl;}
private:T _a;K _b;
};
template<>
class date<int,char>
{
public:date(){cout << "22222222222" << endl;}
private:int _a;char _b;
};
template<typename T >
class date< T , char >
{
public:date(){cout << "3333333333" << endl;}
private:T _a;char _b;
};
int main()
{date<int, char> s;date<char, char> k;date<int, int> q;
}
限制特化

以某个性质限制,列如指针 ,引用

#include<iostream>
#include<deque>
#include<algorithm>
#include<vector>template<typename T>
class Less
{
public:bool operator() (const T& x, const T& y){return x < y;}
};
template<typename T>
class Less<T*>// 限制特化 只有指针才能进入这里
{
public:bool operator()( T* x, T* y){return *x < *y;}
};template<typename T>
class Less<T&>// 限制特化 只有引用才能进入这里
{
public:bool operator()( T& x, T& y){return x < y;}
};template<typename T>
class Greater
{
public:bool operator() (const T& x, const T& y){return y < x;}
};class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& s){if (s._year > _year)return true;else if (s._year == _year){if (s._month > _month)return true;else if (s._month == _month){if (s._day > _day)return true;}}return false;}
private:int _year;int _month;int _day;
};
int main()
{Date* p1 = new Date(2024, 1, 1);Date* p2 = new Date(2024, 1, 4);Less<Date*> ls;cout << ls(p1 , p2) << endl;return 0;
}


http://www.ppmy.cn/server/35527.html

相关文章

Linux—-vim基础使用

1、基本概念 Vim的工作模式有四种&#xff0c;普通模式&#xff0c;输入模式&#xff0c;命令模式&#xff0c;可视模式。 在终端中打开vim&#xff0c;只需要输入vim 文件&#xff0c;在普通模式下按i就会进入到输入模式&#xff0c;按下:进入命令模式&#xff0c;输入:q就可…

基于Spring EL表达式处理业务表达式

文章目录 简介Spring EL的常见应用Value处理注解xml中使用 Spring EL表达式基本表达式模板函数表达式 Spring EL定制引用Spring的bean 简介 SpringEL是Spring表达式&#xff0c;功能非常强大。 我们可以能在Value、Cachable、自定义注解中的应用EL表达式&#xff0c;当然这些…

前端面试题(二)

面试形式&#xff1a;线上面试&#xff08;不露脸&#xff09;&#xff1a;时长40分钟 面试评价&#xff1a;由易到难&#xff0c;由细到全&#xff0c;比较不错 面试官&#xff1a;项目经理 面试官提问&#xff08;面试题&#xff09;&#xff1a; 1、聊聊最近写的这个项目…

Rust Rocket创建第一个hello world的Web程序 Rust Rocket开发常用网址和Rust常用命令

一、Rust Rocket简介 Rust Rocket 是一个用 Rust 语言编写的 Web 应用框架&#xff0c;它结合了 Rust 的安全性和性能优势&#xff0c;以及 Web 开发的便利性。以下是 Rust Rocket 框架的一些优点&#xff1a; 安全性&#xff1a;Rust 是一种注重安全性的编程语言&#xff0c;…

C语言创建文件夹和多级目录

C调用系统命令创建多级目录 #include <stdio.h> #include <stdlib.h>int main() {const char *path "a/b/c";// 创建目录命令的字符串char mkdir_command[100];sprintf(mkdir_command, "mkdir %s", path);// 调用系统命令system(mkdir_comma…

数据库原理与应用实验三 嵌套查询

实验目的和要求 加深和掌握对嵌套查询的理解和应用 实验环境 Windows10 SQLServer 实验内容与过程 图书&#xff08;书号&#xff0c;书名&#xff0c;价格&#xff0c;出版社&#xff09; 读者&#xff08;卡号&#xff0c;姓名&#xff0c;年龄&#xff0c;所属单位&a…

扭矩法是什么拧紧工艺?——SunTorque智能扭矩系统

智能扭矩系统-智能拧紧系统-扭矩自动控制系统-SunTorque 扭矩法是一种在拧紧工艺中广泛使用的预紧力控制方法。它基于扭矩与预紧力的线性关系&#xff0c;通过控制扭矩值来实现对被连接件的预紧。这种方法的优点在于操作简单&#xff0c;只需对扭矩进行控制即可。 在扭矩法拧…

浅记SpringBoot3源码中应用的JDK新特性

问题背景 在看SpringBoot3涉及到SpringMVC源码的时候&#xff0c;看到这么个东西。 // Bean name or resolved handler?if (handler instanceof String handlerName) {handler obtainApplicationContext().getBean(handlerName);}在想这是什么操作&#xff1f; 后来查到这是…