C++类模板参数

C++类模板参数

12.4 C++ non-type

12.4.1 格式

template <class T, int n>
//这里的n就是non-type(表达式或参数)

12.4.2 non-type的几点要求

  • 1.可以是int,枚举,参考,指针类型;不允许double类型,但是允许是double的参考和指针类型
  • 2.不能更改n的值,也不可以获取n的地址
  • 3.当初始化n时,要求是常量(constant)

12.4.3 non_type的优缺点

优点:存储在存储自动变量的堆栈中,相比于使用new and delete自动内存分配来说速度快一些,特别对于小数组。
缺点:每个数组大小都生成自己的模板,也就是根据模板和大小(只要两者任意一个与之前的有不同)生成各自的类声明,会占用存储空间。
但是不包含non-type的模板类是使用类构造函数确定大小的,因此只需要一个声明。
(类构造函数更通用,适合将某个大小的数组赋值给另一个大小的数组或者调整数组大小)

12.4.4 举例—arraytp类

arraytp.h

#pragma once
//arraytp.h -- Array Template
#ifndef ARRAYTP_H_
#define ARRAYTP_H_
#include <iostream>
#include <cstdlib>
#include<cstring>
template <class T, int n>
class ArrayTP
{
private:
	T ar[n];
public:
	ArrayTP() {};
	explicit ArrayTP(const T& v);
	virtual T& operator[](int i);
	virtual T operator[](int i) const;
};
template <class T, int n>
ArrayTP<T, n>::ArrayTP(const T& v)
{
	for (int i = 0; i < n; i++)
		ar[i] = v;
}
template <class T, int n>
T& ArrayTP<T, n>::operator[](int i)
{
	if (i < 0 || i >= n)
	{
		std::cerr << "Error in array limits: " << i
			<< " is out of range\n";
		std::exit(EXIT_FAILURE);
	}
	return ar[i];
}
template <class T, int n>
T ArrayTP<T, n>::operator[](int i) const
{
	if (i < 0 || i >= n)
	{
		std::cerr << "Error in array limits: " << i
			<< " is out of range\n";
		std::exit(EXIT_FAILURE);
	}
	return ar[i];
}
template<typename T>
using arrtype = ArrayTP<T, 12>; // template to create multiple aliases
#endif

12.6 C++对模板类pairs

12.6.1 简介

模板包含多个类型参数。

格式:

template <class T1, class T2>

12.6.2 代码

pairs.h

#pragma once
#ifndef PAIRS_H_
#define PAIRS_H_
//双模板的声明
template <class T1, class T2>
class Pair
{
private:
	T1 a;
	T2 b;
public:
	T1& first();
	T2& second();
	T1 first() const { return a; }
	T2 second() const { return b; }
	Pair(const T1& aval, const T2& bval) : a(aval), b(bval) { }
	Pair() {}
};
template<class T1, class T2>
T1& Pair<T1, T2>::first()
{
	return a;
}
template<class T1, class T2>
T2& Pair<T1, T2>::second()
{
	return b;
}
#endif

main.h

#pragma once
#ifndef MAIN_H_
#define MAIN_H_
#include <iostream> //输入输出 
#include <string> //simple_template、template_pairs
#include "pairs.h" //template_pairs
using namespace std;
void template_pairs(void)
{
	std::cout << "\ntemplate_pairs Hello******************************************************\n";
	using std::cout;
	using std::endl;
	using std::string;
	Pair<string, int> ratings[4] =
	{
		Pair<string, int>("The Purpled Duck", 5),//Pair<string, int>这个是为了触发Pair类的构造函数
		Pair<string, int>("Jaquie's Frisco Al Fresco", 4),
		Pair<string, int>("Cafe Souffle", 5),
		Pair<string, int>("Bertie's Eats", 3)
	};
	int joints = sizeof(ratings) / sizeof(Pair<string, int>);
	cout << "Rating:\t Eatery\n";
	for (int i = 0; i < joints; i++)
		cout << ratings[i].second() << ":\t "
		<< ratings[i].first() << endl;
	cout << "Oops! Revised rating:\n";
	ratings[3].first() = "Bertie's Fab Eats";
	ratings[3].second() = 6;
	cout << ratings[3].second() << ":\t "
		<< ratings[3].first() << endl;
	std::cout << "template_pairs Bye**************************************************************\n";
}
#endif

main.cpp

/*
Project name :			_12template
Last modified Date:		2022年5月6日11点33分
Last Version:			V1.0
Descriptions:			对模板类pairs
*/
#include "main.h"

int main()
{
	cout << "对模板类pairs******************************************************************" << endl;
	template_pairs();

	return 0;
}

12.6.3 运行结果

对模板类pairs******************************************************************
template_pairs Hello******************************************************
Rating:  Eatery
5:       The Purpled Duck
4:       Jaquie's Frisco Al Fresco
5:       Cafe Souffle
3:       Bertie's Eats
Oops! Revised rating:
6:       Bertie's Fab Eats
template_pairs Bye**************************************************************

D:\Prj\_C++Self\_12template\Debug\_12template.exe (进程 12356)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

12.7 C++默认类型模板参数

12.7.1 格式

template <class T1,class T2 = int> class Topo{...};

12.7.2 意义

就是默认情况下T2的类型为int(和默认参数差不多,给值就为给的值,不给值就为默认值)

12.7.3 注意事项

可以对类模板使用默认模板参数,不能对函数模板使用默认模板参数;但是可以为类模板或函数模板的non-type提供默认参数。

12.10 模板作为模板的参数

12.10.1 定义

一个模板也可以作为别的模板的参数(例子是Crab类)

12.10.2 格式

template <template <typename T> class Thing>
class Crab

12.10.3 模板参数和其他参数混合使用

template <template <typename T> class Thing, typename U, typename V>
class Crab

12.10.4 代码

Crab.h

#pragma once
#ifndef CRAB_H_
#define CRAB_H_
#include "stacktp.h"
template <template <typename T> class Thing>
class Crab
{
private:
	Thing<int> s1;
	Thing<double> s2;
public:
	Crab() {};
	// assumes the thing class has push() and pop() members
	bool push(int a, double x) { return s1.push(a) && s2.push(x); }
	bool pop(int& a, double& x) { return s1.pop(a) && s2.pop(x); }
};
#endif

main.h

#pragma once
#ifndef MAIN_H_
#define MAIN_H_
#include <iostream> //输入输出 
#include "stacktp.h" //simple_template、pointer_template
#include "Crab.h"
using namespace std;
void Templates_As_Parameters(void)
{
	cout << "Templates_As_Parameters Hello*********************************************" << std::endl;
	Crab<Stack> nebula;
	// Stack must match template <typename T> class thing
	int ni;
	double nb;
	cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
	while (cin >> ni >> nb && ni > 0 && nb > 0)
	{
		if (!nebula.push(ni, nb))
			break;
	}
	while (nebula.pop(ni, nb))
		cout << ni << ", " << nb << endl;
	std::cout << "Templates_As_Parameters Bye********************************************\n";
}
#endif

main.cpp

/*
Project name :			_12template
Last modified Date:		2022年5月6日11点33分
Last Version:			V1.0
Descriptions:			模板作为模板的参数
*/
#include "main.h"

int main()
{
	cout << "模板作为模板的参数**************************************************************" << endl;
	Templates_As_Parameters();

	return 0;
}

12.10.5 运行结果

模板作为模板的参数**************************************************************
Templates_As_Parameters Hello*********************************************
Enter int double pairs, such as 4 3.5 (0 0 to end):
7 8.9
9 8.8
0 0
9, 8.8
7, 8.9
Templates_As_Parameters Bye********************************************

D:\Prj\_C++Self\_12template\Debug\_12template.exe (进程 13724)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

12.13 可变参数模板

12.13.1 定义

就是可创建可接受可变数量的参数的模板函数和模板类

12.13.2 模板参数包

C++11提供了一个用省略号表示的元运算符,能够声明表示模板参数包的标识符,模板参数包基本上是一个类型列表。

template<typename... Args> // Args is a template parameter pack
void show_list1(Args... args) // args is a function parameter pack
{
	...
}

其中Args是一个模板参数包,而args是一个函数参数包,名称要符合命名规范;函数参数包args包含的值列表与模板参数包Args包含的类型列表匹配—无论是类型还是数量。

12.13.3 展开参数包

索引不再适用

12.13.3.1 省略号后置
template<typename... Args> // Args is a template parameter pack
void show_list1(Args... args) // args is a function parameter pack
{
	show_list1(args...); // passes unpacked args to show_list1()
}

但是存在缺陷,就是该函数调用与原始调用相同,因此它将使用相同的参数不断调用自己,导致无限递归。

12.13.3.2 使用递归

将函数参数包展开,对列表中的第一项进行处理,再将余下的内容传递给递归调用;以此类推,直到列表为空。

template<typename T, typename... Args>
void show_list3( T value, Args... args)

12.13.4 代码

main.h

#pragma once
// stacktem.cpp -- testing the template stack class
#ifndef MAIN_H_
#define MAIN_H_
#include <iostream> //输入输出 

// definition for 0 parameters
void show_list() {}
// definition for 1 parameter
template<typename T>
void show_list(const T& value)
{
	std::cout << value << '\n';
}
// definition for 2 or more parameters
template<typename T, typename... Args>
void show_list(const T& value, const Args&... args)
{
	std::cout << value << ", ";
	show_list(args...);
}
void Templates_Variadic(void)
{
	std::cout << "\nTemplates_Variadic Hello************************************************\n";
	int n = 14;
	double x = 2.71828;
	std::string mr = "Mr. String objects!";
	show_list(n, x);
	show_list(x * x, '!', 7, mr);
	std::cout << "\nTemplates_Variadic Bye************************************************\n";
}

#endif

main.cpp

/*
Project name :			_12template
Last modified Date:		2022年5月6日11点33分
Last Version:			V1.0
Descriptions:			模板总结
*/
#include "main.h"

int main()
{
	cout << "可变参数模板******************************************************************" << endl;
	Templates_Variadic();

	return 0;
}

12.13.5 运行结果

可变参数模板******************************************************************
Templates_Variadic Hello************************************************
14, 2.71828
7.38905, !, 7, Mr. String objects!

Templates_Variadic Bye************************************************

D:\Prj\_C++Self\_12template\Debug\_12template.exe (进程 10524)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jasmine-Lily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值