• C++类模板参数


    C++类模板参数

    12.4 C++ non-type

    12.4.1 格式

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

    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 
    #include 
    #include
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    12.6 C++对模板类pairs

    12.6.1 简介

    模板包含多个类型参数。

    格式:

    template <class T1, class T2>
    
    • 1

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    main.h

    #pragma once
    #ifndef MAIN_H_
    #define MAIN_H_
    #include  //输入输出 
    #include  //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这个是为了触发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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    12.7.1 格式

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

    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
    
    • 1
    • 2

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

    template <template <typename T> class Thing, typename U, typename V>
    class Crab
    
    • 1
    • 2

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    main.h

    #pragma once
    #ifndef MAIN_H_
    #define MAIN_H_
    #include  //输入输出 
    #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  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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
    {
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其中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()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    12.13.3.2 使用递归

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

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

    12.13.4 代码

    main.h

    #pragma once
    // stacktem.cpp -- testing the template stack class
    #ifndef MAIN_H_
    #define MAIN_H_
    #include  //输入输出 
    
    // 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

  • 相关阅读:
    Vue3的其他组和API—— toRaw与markRaw、customRef、 provide 与inject
    Java——AOP案例之测量业务层接口执行效率
    2023高教社杯 国赛数学建模C题思路 - 蔬菜类商品的自动定价与补货决策
    新手python爬虫100个入门项目
    网络编程学习
    Python吴恩达深度学习作业11 -- 卷积神经网络的实现
    【电脑使用】CCleaner使用的坑
    【python数据分析刷题】-N02.数据索引
    [FFmpeg学习]windows环境sdl播放音频试验
    [运维|数据库] mysql的charset与PostgreSQL的encoding
  • 原文地址:https://blog.csdn.net/weixin_44410704/article/details/127983617