【C++】泛型编程——模板进阶

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

前言

在之前的文章里,我们进行了模板初阶的学习( 【C++】泛型编程——模板初阶),了解了什么是泛型编程,学习了函数模板和类模板。
那这篇文章,我们继续学习模板进阶的内容的学习。

1. 模板参数的分类

首先我们来回顾一下:

我们在模板初阶的学习中,定义模板参数是怎么定义的?
是不是使用class或者typename关键字啊,
template<class T1, class T2,...,class Tn>
【C++】泛型编程——模板进阶,C++,c++,开发语言
对于函数模板来说,我们调用函数时,传的参数是什么类型,T就会被替换成对应的类型,然后实例化出对应的模板函数,我们实际调用的就是函数模板根据具体传入的实参类型实例化出来的模板函数。
【C++】泛型编程——模板进阶,C++,c++,开发语言

那对于跟在class或者typename之后的这种模板参数,我们把它叫做类型模板参数

即它定义的是一个类型,对应的模板实例化的时候该参数会被替换成一个具体的类型,供其对应的模板类或模板函数使用。

但是呢,这其实只是模板参数的一种:

模板参数分为类型模板参数非类型模板参数

类型模板参数我们已经了解了:

类型形参即:出现在模板参数列表中,跟在class或者typename关键字之后的参数类型名称。

那非类型模板参数又是什么呢?

2. 非类型模板参数

2.1 非类型模板参数的概念

非类型模板参数的概念:

非类型模板参数,就是用一个常量(且必须是整型常量)作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

什么意思呢?下面我们通过一个栗子细细的给大家介绍一下:

2.2 铺垫

假设我们现在要写一个静态的顺序表,那我们就可以这样搞

【C++】泛型编程——模板进阶,C++,c++,开发语言
首先这里我们定义了一个标识符(宏)常量N,用N作为当前静态数组的大小,就使得我们后续想要改变数组大小的时候很方便。
其次,我们把它实现成了一个类模板,该类模板有一个模板参数T,那通过上面的了解我们知道这里的T其实就是一个类型模板参数,它定义的是一个类型,这样我们在使用该类模板的时候,指定什么类型,实例化出来的数组(模板类)就存放什么类型的数据。
【C++】泛型编程——模板进阶,C++,c++,开发语言
这样看起来好像也挺方便的。

但是对于有些情况却不能很好的处理:

如果我们现在想达到这样一种效果,我们想让a1的大小为10 ,而a2的大小为20,目前的实现可以做到吗?
不行啊,虽然这里我们用来#define定义的宏,改变数组的大小是很方便的,但是,这里我们实例化出两个对象,一个大小为10,一个20,是不是做不到啊。

那大家来思考一下:

首先对于类型模板参数来说,他解决了类型的问题。
我们没有学模板之前,写一个数据结构,比如有一个栈,我们一般会有一个typedef,这样想要改变栈里存储的数据的类型很方便,但是如果我们在main函数里定义了2个或者多个栈,想让它们分别存储不同类型的数据,能不能做到呢?
如果typedef的话是不能的,但是在模板初阶的学习之后,借助模板,用类型模板参数是不是就可以解决这个问题啊!
【C++】泛型编程——模板进阶,C++,c++,开发语言【C++】泛型编程——模板进阶,C++,c++,开发语言
这样在一个main函数中,我们定义两个栈,就可以让他们分别存储不同类型的数据。

2.2 非类型模板参数的使用

那再回到我们上面的问题,其实这里有点类似:

类型模板参数呢?解决了类型的问题。
那这里我们想让a1大小为10,a2大小为20
【C++】泛型编程——模板进阶,C++,c++,开发语言
与类型无关啊,那这种情况又该如何解决呢?
🆗,那非类型模板参数的引入,其实就很好的解决了这种问题

类型模板参数定义了一个类型,那非类型模板参数定义的是什么呢?

我们再来回顾一下非类型模板参数的概念:
非类型模板参数,就是用一个常量(且必须是整型常量)作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
是的,非类型模板参数其实定义的是一个整型常量。
注意:这里的整型不单指int,而是整个整型家族(包括C99引入的bool类型)。

具体怎么用呢?这里我们就可以这样写:

【C++】泛型编程——模板进阶,C++,c++,开发语言
和类型模板参数一样,直接放在模板参数列表里面就行了。
我们看到这里是这样写的——size_t N,虽然没加const,但是规定它在这里就是常量。
后面我们会验证它是不能修改的。

那这样就可以实现a1的大小是10,a2的大小是20了。

【C++】泛型编程——模板进阶,C++,c++,开发语言

当然:

非类型模板参数也是可以给缺省值的。
【C++】泛型编程——模板进阶,C++,c++,开发语言

2.4 注意

再次提醒大家:

非类型模板参数必须是常量且要是整型。

我们可以来验证一下:

这次我们举个函数模板的例子:
首先常量就意味着它不能被修改
【C++】泛型编程——模板进阶,C++,c++,开发语言
其次必须是整型
【C++】泛型编程——模板进阶,C++,c++,开发语言
所以说:
浮点数、类对象以及字符串等其它非整形的类型是不允许作为非类型模板参数的。
不过呢,这里提一下,就是C++20允许使用float或double作为非类型模板参数。
【C++】泛型编程——模板进阶,C++,c++,开发语言
另外要知道:
非类型的模板参数必须在编译期间就能确认结果。

2.5 array的了解

然后我们再来了解一个东西就是:

C++11搞出来了一个新容器——array
其实可以认为就是静态数组,我们看到文档给的解释是固定大小的序列容器
【C++】泛型编程——模板进阶,C++,c++,开发语言
我们看到array这个类模板其实就用了一个非类型模板参数来作为这个数组的大小。
可以看一下它的成员函数
【C++】泛型编程——模板进阶,C++,c++,开发语言

🆗,那C++11搞出来这个东西

其实是对标C语言里的静态数组:
我们包一下<array>这个头文件就可以使用它
【C++】泛型编程——模板进阶,C++,c++,开发语言
那array的底层其实也是一个静态数组,只不过用类进行了封装。

那大家想一下,本来就已经有静态数组了,为什么还要搞出来一个这个,或者说,它于C语言的静态数组相比,有什么进步吗?

嗯~,array可以用迭代器,而数组不能。
是,虽然数组不能用迭代器,但是它也可以用范围for啊,范围for用起来就很方便啊。
那这样看来好像没什么特别之处啊,难道array可以自动初始化?
【C++】泛型编程——模板进阶,C++,c++,开发语言
并没有。
没啥用啊,与原生的数组相比好像没啥进步啊。
🆗,其实它的优势是对越界的一个检查比数组更严格一点
传统的数组对于越界的检查是一个抽查,有时候越界会报错,而有时候可能就不会
【C++】泛型编程——模板进阶,C++,c++,开发语言
【C++】泛型编程——模板进阶,C++,c++,开发语言
越界读,不会报错。
如果越界写:
【C++】泛型编程——模板进阶,C++,c++,开发语言
【C++】泛型编程——模板进阶,C++,c++,开发语言
就不一定了,所以我们说是抽查。

那对于array来说:

它对于读写的检查就比较严格,比较全面

【C++】泛型编程——模板进阶,C++,c++,开发语言

【C++】泛型编程——模板进阶,C++,c++,开发语言
因为它是一个类嘛,它里面可以拿非类型模板参数这个N去比较,判断你是否越界。
【C++】泛型编程——模板进阶,C++,c++,开发语言

所以要说它比传统数组的进步的话,可能就这一个点了吧。

所以C++11搞出来这个其实是想让我们以后用数组的时候都用array。
但是大家想一下如果给我们选择的话我们会用这个嘛?
是不是又vector啊,我vector如果越界也能很好的检查啊,并且我vector还能直接初始化,array有哪一点比vector强。

所以,这个设计就感觉有点没必要了😂。
如果要论array和vector的区别的话,那就是array的空间是在栈上开辟的,而vector的空间是在堆上申请的。

所以这个大家了解一下就行,没什么用。

3. 模板的特化

接下来我们再来学一个东西叫做模板的特化。
首先我们来认识一下它的概念。

3.1 概念

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

举个栗子:
我们这里现在有一个专门用来进行小于比较的函数模板

template<class T>
bool Less(T left, T right)
{
	return left < right;
}

那我们现在就可以使用它去比较不同类型数据的大小:

int main()
{
	cout << Less(1, 5) << endl; // 可以比较,结果正确
	return 0;
}

我们来看一下结果:

【C++】泛型编程——模板进阶,C++,c++,开发语言
没有问题,结果正确。

现在我们拿过来一个日期类:

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	bool operator<(const Date& d)const
	{
		return (_year < d._year) ||
			(_year == d._year && _month < d._month) ||
			(_year == d._year && _month == d._month && _day < d._day);
	}
	bool operator>(const Date& d)const
	{
		return (_year > d._year) ||
			(_year == d._year && _month > d._month) ||
			(_year == d._year && _month == d._month && _day > d._day);
	}
private:
	int _year;
	int _month;
	int _day;
};

他已经重载了大于小于操作符。

那我们现在相比较日期类的大小:

【C++】泛型编程——模板进阶,C++,c++,开发语言
看一下结果:
【C++】泛型编程——模板进阶,C++,c++,开发语言
没有问题,结果也是正确的。
但是,这样呢?
【C++】泛型编程——模板进阶,C++,c++,开发语言
我们再来运行看结果:
【C++】泛型编程——模板进阶,C++,c++,开发语言
欸,p1指向的日期小于p2指向的日期啊,那结果怎么是0呢?
🆗,因为这里比较的并不是它们指向的日期,而是这两个指针本身,那指针进行比较的话实际比较的是它们存储的地址的大小,所以这里的结果可能并不是我们想要的。
可以看到,Less绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果。
上述示例中,p1指向的d1显然小于p2指向的d2对象,但是Less内部并没有比较p1和p2指向的对象内容,而比较的是p1和p2指针的地址,这就无法达到预期而错误。

那如果我们就想比较日期,即使我们拿到的是date*的指针,我们也想按日期去比较,怎么办?

🆗,我们在优先级队列那篇文章是不是解决过这个问题啊,可以写一个仿函数去搞定这个问题。
那除了仿函数,还有没有其它方法来解决呢?
有的,我们还可以使用模板特化去解决这个问题。

那模板特化到底是什么呢?

模板特化即在原模板的基础上,针对特殊类型所进行特殊化的实现
模板特化中分为函数模板特化类模板特化

3.2 函数模板特化

首先我们来看函数模板特化,我们说上面那种情况可以用模板特化去解决。

那现在问题来了,对于一个像上面那样的函数模板,我们想对其进行特化,要怎么做呢?或者说步骤是什么?

🆗,来看,函数模板特化的步骤:

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

那这个我们已经有了啊

template<class T>
bool Less(T left, T right)
{
	return left < right;
}

接着要怎么做呢?
🆗,特化出来的版本是这样的:

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

那我们现在要对Date*这种类型进行特化,所以函数名后面的尖括号里面放的就是Date*
【C++】泛型编程——模板进阶,C++,c++,开发语言
那我们想要的是比较它们指向的日期的大小,所以现在函数体应该这样实现:
【C++】泛型编程——模板进阶,C++,c++,开发语言
至此我们的特化就完成了。

那我们来试一下这次的结果是否正确:

【C++】泛型编程——模板进阶,C++,c++,开发语言
🆗,这下结果就正确了。

我们实现了特化的版本之后:

对于那些普通的类型,就还是走普通版本的逻辑
【C++】泛型编程——模板进阶,C++,c++,开发语言
而一旦遇到我们特化的类型,他就会走特化版本的逻辑。
【C++】泛型编程——模板进阶,C++,c++,开发语言
所以模板特化就是针对某些特殊类型进行特殊化的处理。

当然,其实针对上面这种情况,我们不使用模板特化也能很轻松解决:

我们可以直接针对Date*这种类型,写一个函数出来啊:
【C++】泛型编程——模板进阶,C++,c++,开发语言
【C++】泛型编程——模板进阶,C++,c++,开发语言
这样也可以啊。
该种实现简单明了,代码的可读性高,容易书写。

是的,所以说:

函数模板不建议特化,一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将处理该情况的函数直接给出,而不是对其进行特化。
所以对于函数模板特化我们这里也不再继续介绍更多的内容了。

3.3 类模板特化

接下来我们再来学习一下类模板的特化:

首先我们要知道模板的特化其实分为两种——全特化和偏特化

3.3.1 全特化

全特化即将模板参数列表中所有的参数都确定化。

举个栗子,现在有这样一个类模板:

template<class T1, class T2>
class Data
{
public:
	Data() 
	{ 
		cout << "Data<T1, T2>" << endl; 
	}
private:
	T1 _d1;
	T2 _d2;
};

那我们现在想对这个类模板进行全特化,怎么做呢?

那就是把该类模板模板参数列表的所有参数都确定化嘛。
【C++】泛型编程——模板进阶,C++,c++,开发语言

那此时如果我们实例化该类模板的时候:

【C++】泛型编程——模板进阶,C++,c++,开发语言
如果我们指定的类型是<int, char>,那就匹配全特化的版本,因为我们的全特化就是把它确定成了<int, char>,那其它类型就匹配的是原始的版本。

3.3.2 偏特化

那什么是偏特化呢?
偏特化有以下两种表现方式:

部分特化
  1. 部分特化
    将模板参数类表中的一部分参数特化(确定化)

什么意思?举个栗子:

还是上面那个Data类模板
【C++】泛型编程——模板进阶,C++,c++,开发语言
那我们想对它进行部分特化,比如把第二个参数特化成int,就是这样搞:
【C++】泛型编程——模板进阶,C++,c++,开发语言
【C++】泛型编程——模板进阶,C++,c++,开发语言

参数更进一步的限制
  1. 参数更进一步的限制
    针对模板参数更进一步的条件限制所设计出来的一个特化版
    本。

什么意思呢?举个栗子:
现在这里有一个用来进行小于比较的仿函数

template<class T>
struct Less
{
	bool operator()(const T& l, const T& r) const
	{
		return l < r;
	}
};

【C++】泛型编程——模板进阶,C++,c++,开发语言

我们来用它比较一些内置类型数据的大小,包括我们的日期类(重载了><),都是没什么问题的。
当然如果我们比Date*的话,还是比较的是地址的大小,如果我们想让他比较指针指向的数据的大小,我们可以对Date* 这个类型进行一个特化(那在这里其实就是一个全特化)。

但是,如果我们不只针对Date*的指针,对于其它类型的指针,比较时我们也想去比较它们指向的内容,而不是地址。
那我们可以怎么做呢?难道对不同的指针类型都进行一个特化吗?

这显然是很麻烦的。
那我们此时就可以用偏特化的第二种形式——参数更进一步的限制来解决这个问题。

怎么做呢?
【C++】泛型编程——模板进阶,C++,c++,开发语言

进行一个偏特化,将模板参数限制成T*,这样只要调用仿函数时传的数据是指针类型,都会去匹配偏特化的这个版本,对指针指向的内容进行比较,而不是存储的地址。

我们来运行看一下:
【C++】泛型编程——模板进阶,C++,c++,开发语言
这下就可以了。
【C++】泛型编程——模板进阶,C++,c++,开发语言

4. 模板分离编译

然后我们再来学习一个东西叫做模板分离编译。

大家还记不记得我们在模板初阶的学习中,文章最后我们提到一个东西,就是我们定义一个类可能习惯头文件和源文件分开来,那普通类这样搞是没问题的,就像我们之前实现的日期类就是多文件管理的。
但是呢,类模板不行,类模板如果这样搞,会链接错误的。

那这篇文章在这里,我们就会来解释一下其中的原因。

4.1 什么是分离编译

我们先来了解一下,什么是分离编译:

分离编译模式源于C语言,在C++语言中继续沿用。
简单地说,分离编译模式是指:一个程序(项目)由若干个源文件(或在加上若干头文件)共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程。

4.2 模板的分离编译

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

【C++】泛型编程——模板进阶,C++,c++,开发语言
除了模板函数之外,我还加了一个普通函数,也是声明定义分开。

然后我们在test.cpp的main函数中去调用模板函数和普通函数,我们会发现:

【C++】泛型编程——模板进阶,C++,c++,开发语言
普通函数func分离编译时没问题的,可以正常调用,没有报错。
但是:
【C++】泛型编程——模板进阶,C++,c++,开发语言
我们发现模板是不行的,它报了一个链接错误。

那为什么呢?为什么模板分离编译不行呢?

🆗,那我们接下来就来分析一个当前这个程序编译链接的一个过程(复习相关知识可看之前的这篇文章:【C进阶】——我们写的代码是如何一步步变成可执行程序(.EXE)的?),看能不能发现其中的原因。
那大致的过程呢差不多是这个样子的:
【C++】泛型编程——模板进阶,C++,c++,开发语言
在里面这个编译的过程中,会把预处理之后的C++代码转换为汇编代码(由一系列汇编指令组成),而函数的地址信息其实就包含在这些汇编指令中。
但是呢,对于当前这个程序来说,编译(func.i——>func.s)的过程中,只会生成func函数的汇编指令,而并没有函数模板Add的。
因为Add没有被实例化,为什么没实例化呢,函数模板实例化不是在编译期间就会进行吗?
因为func.cpp和test.cpp是分开的,链接之前它们都是单独进行的,test.cpp里面指定了具体类型对Add进行实例化,但是func.cpp编译的时候没法确定类型,因为在链接之前它们不交互,所以func.cpp里面的函数模板没法确定T要替换成什么类型,所以没法实例化。
那然后我们再来分析一下,main函数中在调用它们的时候这个过程是怎么样的?
【C++】泛型编程——模板进阶,C++,c++,开发语言
首先在test.c编译的过程中这几句代码肯定也会被变成汇编代码
【C++】泛型编程——模板进阶,C++,c++,开发语言
那函数调用转换成对应的汇编代码其实就是去call这个函数的地址。
但是呢,test.c包含了头文件"func.h",而"func.h"里面只有Add和func的声明,并没有具体的函数定义和对应的实例化生成的具体函数,所以这里生成的符号表里面,它们的地址可能知识标识一下,无实际意义。
但是有声明的话这里编译也可以通过。
可是呢?后面链接的时候就有问题了:
我们知道连接的时候会做一件事情叫做符号表的合并和重定位,然后就可以拿到这些函数重定位之后有效的地址,就可以成功调用它们了。
那func函数在func.cpp中是有具体的定义的,所以最终的符号表中会有它有效的地址。
但是,由于Add并没有成功进行实例化,没有生成具体的函数定义,所以就找不到有效的地址,所以符号表合并和重定位之后,里面并没有有效的函数地址,可能还是声明产生的那个无效的,没有意义的地址
【C++】泛型编程——模板进阶,C++,c++,开发语言
所以这里两个Add就无法调用,由于是在链接阶段出现的错误,所以报的错是链接错误error LNK
大家也可以看一下这张图:
【C++】泛型编程——模板进阶,C++,c++,开发语言

那通过上面的分析我们可以得出:

其实模板分离编译导致出错的原因关键就在于这些多个文件是分离编译的,在链接之前它们是不会进行交互的,所以没法实例化,没法产生具体的函数或类,因为不交互的话,类型都没法确定。
所以最后链接的时候就没法找的有效的地址,就出现了链接错误。

4.3 解决方法

那针对上面的问题,有没有什么解决方法呢?
有的,这里有两种解决方法:

  1. 在模板定义的位置显式实例化

举个栗子:

【C++】泛型编程——模板进阶,C++,c++,开发语言
对于Add这个模板,你在main函数里面不是实例化了两份嘛,一份是int,一份是double。
那我们就针对这两个在模板定义的位置显示实例化一下,怎么做呢?
【C++】泛型编程——模板进阶,C++,c++,开发语言
写法是这样的。
然后我们再来运行:
【C++】泛型编程——模板进阶,C++,c++,开发语言
就可以了。
但是我们发现,这种方法的,增加一个新类型,我们就要增加一个显式实例化,很麻烦。
所以不推荐这种方法。

那有没有好一点的方法呢?有的

  1. 声明和定义可以分离,但放到一个文件中

什么意思呢?

就是你可以把模板的声明和定义分开来写,但是不要分成一个头文件,一个源文件,而是把它们放到一个.h或者一个.hpp文件里面。(有的头文件为了暗示是模板会将后缀改成.hpp,但还是头文件)
【C++】泛型编程——模板进阶,C++,c++,开发语言
【C++】泛型编程——模板进阶,C++,c++,开发语言
这样就不会出错了。推荐使用这种。

所以如果遇到需要分离的场景建议大家使用第二种方式。

5. 模板总结

最后我们来对模板进行一个简单的总结:

5.1 优点

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性

5.2 缺点

  1. 模板会导致代码膨胀问题,也会导致编译时间变长
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

关于模板的讲解就先到这里。
【C++】泛型编程——模板进阶,C++,c++,开发语言文章来源地址https://www.toymoban.com/news/detail-569371.html

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

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

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

相关文章

  • 【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【C++初阶】七、内存管理 (C/C++内存分布、C++内存管理方式、operator new / delete 函数、定位new表

    2024年02月04日
    浏览(32)
  • 【C++基础(十)】C++泛型编程--模板初阶

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C++从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C++   🔝🔝 在学习数据结构时会遇见以下的情况 数据结构中存储的类型往往不能确定 所以在实现数据结构时往往是这样做的 在写代码时用DateType来表

    2024年02月13日
    浏览(22)
  • C++——模板初阶与泛型编程

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 本章我们

    2023年04月17日
    浏览(30)
  • 【C++】泛型编程 ② ( 函数模板与普通函数区别 )

    函数模板与普通函数区别 : 主要区别在于它们能够处理的 数据类型数量 和 灵活性 ; 自动类型转换 : 函数模板 不允许 自动类型转化 , 会进行严格的类型匹配 ; 普通函数 能够进行 自动类型转换 , 内含隐式的类型转化 ; 参数 / 返回值 数据类型 : 普通函数 只接受 特定类型 参数

    2024年02月20日
    浏览(27)
  • 【C++】泛型编程 ③ ( 函数模板 与 普通函数 调用规则 | 类型匹配 | 显式指定函数模板泛型类型 )

    上一篇博客 【C++】泛型编程 ② ( 函数模板与普通函数区别 ) 中 , 分析了 函数参数 类型匹配 下的 普通函数 与 函数模板 的调用规则 ; 为 函数模板 重载了 普通函数 , 普通函数有指定的类型 ; 传入实参 , 调用 普通函数 还是 模板函数 , 是有一定的规则的 ; 普通函数 与 传入实

    2024年02月21日
    浏览(30)
  • 【c++ primer 笔记】第 16章 模板与泛型编程

    🎉作者简介:👓 博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢 c + + , g o , p y t h o n , 目前熟悉 c + + , g o 语言,数据库,网络编程,了解分布式等相关内容 textcolor{orange}{博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c+

    2024年02月20日
    浏览(28)
  • C++、STL标准模板库和泛型编程 ——适配器、补充(侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一、C++ 面向对象高级开发 1、C++面向对象高级编程(上) 2、C++面向对象高级编程(下) 二、STL 标准库和泛型编程 1、分配器、序列式容器 2、关联式容器 3、迭代器、 算法、仿函数 4、适配器、补充 三、C++ 设计模式 四、C++ 新标准 五、

    2023年04月27日
    浏览(60)
  • C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一、C++ 面向对象高级开发 1、C++面向对象高级编程(上) 2、C++面向对象高级编程(下) 二、STL 标准库和泛型编程 1、分配器、序列式容器 2、关联式容器 3、迭代器、 算法、仿函数 4、适配器、补充 三、C++ 设计模式 四、C++ 新标准 五、

    2023年04月25日
    浏览(38)
  • 【C++】泛型编程 ① ( 函数模板 | 函数模板概念 | 函数模板意义 | 函数模板定义语法 | 函数模板调用语法 | 显式类型调用 | 自动类型推导 )

    在 C++ 语言中 , 泛型编程 的 核心就是 函数模板 和 类模板 ; 函数模板 Function Template 是 C++ 语言 中的 重要特性 ; 函数模板概念 : 建立一个 \\\" 通用函数 \\\" , 不指定该函数的 函数返回值类型 和 函数参数类型 , 仅使用 \\\" 虚拟类型 \\\" 代表 上述 两种类型 , 该 \\\" 通用函数 \\\" 就是 \\\" 函数模

    2024年02月19日
    浏览(28)
  • 玄子Share-自然语言编程(NLP)_Java开发小白向 ChatGPT 提问的最佳模板

    以下内容均为 ChatGPT 回答 玄子: 我向你提问时,问题描述精确的重要性 ChatGPT 3.5 问题描述的精确性非常重要,因为它可以让回答者更好地理解您的问题,并且更容易提供准确和有用的解决方案。如果问题描述不够清晰或不够详细,回答者可能会误解您的问题或者理解不到位

    2023年04月09日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包