template <class T, int n>
//这里的n就是non-type(表达式或参数)
优点:存储在存储自动变量的堆栈中,相比于使用new and delete自动内存分配来说速度快一些,特别对于小数组。
缺点:每个数组大小都生成自己的模板,也就是根据模板和大小(只要两者任意一个与之前的有不同)生成各自的类声明,会占用存储空间。
但是不包含non-type的模板类是使用类构造函数确定大小的,因此只需要一个声明。
(类构造函数更通用,适合将某个大小的数组赋值给另一个大小的数组或者调整数组大小)
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
模板包含多个类型参数。
格式:
template <class T1, class T2>
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 //输入输出
#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
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;
}
对模板类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。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
template <class T1,class T2 = int> class Topo{...};
就是默认情况下T2的类型为int(和默认参数差不多,给值就为给的值,不给值就为默认值)
可以对类模板使用默认模板参数,不能对函数模板使用默认模板参数;但是可以为类模板或函数模板的non-type提供默认参数。
一个模板也可以作为别的模板的参数(例子是Crab类)
template <template <typename T> class Thing>
class Crab
template <template <typename T> class Thing, typename U, typename V>
class Crab
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 //输入输出
#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
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;
}
模板作为模板的参数**************************************************************
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。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
就是可创建可接受可变数量的参数的模板函数和模板类
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包含的类型列表匹配—无论是类型还是数量。
索引不再适用
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()
}
但是存在缺陷,就是该函数调用与原始调用相同,因此它将使用相同的参数不断调用自己,导致无限递归。
将函数参数包展开,对列表中的第一项进行处理,再将余下的内容传递给递归调用;以此类推,直到列表为空。
template<typename T, typename... Args>
void show_list3( T value, Args... args)
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
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;
}
可变参数模板******************************************************************
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。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .