《C++ Templates中文版》——2.3 模板参数

简介:

本节书摘来自异步社区出版社《C++ Templates中文版》一书中的第2章,第2.3节,作者: 【美】David Vandevoorde , 【德】Nicolai M. Josuttis,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.3 模板参数

函数模板有两种类型的参数。

1.模板参数:位于函数模板名称的前面,在一对尖括号内部进行声明:

template <typename T>     //T是模板参数

2.调用参数:位于函数模板名称之后,在一对圆括号内部进行声明:

…max (T const& a, T const& b)  //a和b都是调用参数

你可以根据需要声明任意数量的模板参数。然而,在函数模板内部(这一点和类模板有区别),不能指定缺省的模板实参[4]。例如,你可以定义一个“两个调用参数的类型可以不同的”max()模板:

template <typename T1, typename T2>
inline T1 max (T1 const& a, T2 const& b)
{
  return a < b ? b: a;
}
…
max(4,4.2)   //OK, 但第1个模板实参的类型定义了返回类型

这看起来是一种能够给max()模板传递两个不同类型调用参数的好方法,但在这个例子中,这种方法是有缺点的。主要问题是:必须声明返回类型。对于返回类型,如果你使用的是其中的一个参数类型,那么另一个参数的实参就可能要转型为返回类型,而不会在意调用者的意图。C++并没有提供一种“指定并且选择一个‘最强大类型’”的途径(然而,你可以使用一些tricky模板编程来提供这个特性,详见15.2.4小节)。于是,取决于调用实参的顺序,42和66.66的最大值可以是浮点数66.66,也可以是整数66。另一个缺点是:把第2个参数转型为返回类型的过程将会创建一个新的局部临时对象,这导致了你不能通过引用[]来返回结果。因此,在我们的例子里,返回类型必须是T1,而不能是T1 const&。

因为调用参数的类型构造自模板参数,所以模板参数和调用参数通常是相关的。我们把这个概念称为:函数模板的实参演绎。它让你可以像调用普通函数那样调用函数模板。

然而,如前所述,针对某些特定的类型,你还可以显式地实例化该模板:

template <typename T>
inline T const& max (T const& a, T const& b);
…
max<double>(4,4.2)  //用double来实例化T

当模板参数和调用参数没有发生关联,或者不能由调用参数来决定模板参数的时候,你在调用时就必须显式指定模板实参。例如,你可以引入第3个模板实参类型,来定义函数模板的返回类型:

template <typename T1, typename T2, typename RT>
inline RT max (T1 const& a, T2 const& b);

然而,模板实参演绎并不适合返回类型[6],因为RT不会出现在函数调用参数的类型里面。因此,函数调用并不能演绎出RT。于是,你必须显式地指定模板实参列表。例如:

template <typename T1, typename T2, typename RT>
inline RT max (T1 const& a, T2 const& b);
…
max<int, double, double>(4,4.2)  //OK, 但是很麻烦

到目前为止,我们只是考察了显式指定所有函数模板实参的例子,和不显式指定函数任何模板实参的例子。另一种情况是只显式指定第一个实参,而让演绎过程推导出其余的实参。通常而言,你必须指定“最后一个不能被隐式演绎的模板实参之前的”所有实参类型。因此,在上面的例子里,如果你改变模板参数的声明顺序,那么调用者就只需要指定返回类型:

template <typename RT, typename T1, typename T2>
inline RT max (T1 const& a, T2 const& b);
…
max<double>(4,4.2)  //OK: 返回类型是double

在这个例子里,调用max< double >时显式地把RT指定为double,但其他两个参数T1和T2可以根据调用实参分别演绎为int和double。

可以看出,所有这些修改后的max()版本都不能得到很大的改进。由于在单(模板)参数版本里,如果传递进来的是两个不同类型的实参,你已经可以指定参数的类型(和返回类型)。因此,尽量保持简洁并且使用单参数版本的max()就是一个不错的主意(在接下来的几节里,当讨论其他模板话题的时候,我们将使用这种方法)。

相关文章
|
16天前
|
存储 C++ 容器
C++STL(标准模板库)处理学习应用案例
【4月更文挑战第8天】使用C++ STL,通过`std:vector`存储整数数组 `{5, 3, 1, 4, 2}`,然后利用`std::sort`进行排序,输出排序后序列:`std:vector<int> numbers; numbers = {5, 3, 1, 4, 2}; std:sort(numbers.begin(), numbers.end()); for (int number : numbers) { std::cout << number << " "; }`
19 2
|
27天前
|
编译器 C++
C++入门指南:10分钟带你快速了解模板究竟是什么(建议收藏!!)
C++入门指南:10分钟带你快速了解模板究竟是什么(建议收藏!!)
29 0
|
30天前
|
安全 算法 编译器
【C++ 泛型编程 进阶篇】深入探究C++模板参数推导:从基础到高级
【C++ 泛型编程 进阶篇】深入探究C++模板参数推导:从基础到高级
246 3
|
30天前
|
存储 算法 编译器
【C++ TypeName用法 】掌握C++中的TypeName:模板编程的瑞士军刀
【C++ TypeName用法 】掌握C++中的TypeName:模板编程的瑞士军刀
237 0
|
29天前
|
自然语言处理 编译器 C语言
【C++ 20 新特性】参数包初始化捕获的魅力 (“pack init-capture“ in C++20: A Deep Dive)
【C++ 20 新特性】参数包初始化捕获的魅力 (“pack init-capture“ in C++20: A Deep Dive)
38 0
|
30天前
|
设计模式 程序员 C++
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
258 2
|
16天前
|
程序员 C++
C++语言模板学习应用案例
C++模板实现通用代码,以适应多种数据类型。示例展示了一个计算两数之和的模板函数`add&lt;T&gt;`,可处理整数和浮点数。在`main`函数中,展示了对`add`模板的调用,分别计算整数和浮点数的和,输出结果。
12 2
|
29天前
|
存储 程序员 编译器
【C++ 模板类与虚函数】解析C++中的多态与泛型
【C++ 模板类与虚函数】解析C++中的多态与泛型
46 0
|
29天前
|
算法 编译器 C++
【C++ 模板编程 基础知识】C++ 模板类部分特例化的参数顺序
【C++ 模板编程 基础知识】C++ 模板类部分特例化的参数顺序
21 0
|
30天前
|
设计模式 存储 安全
【C++ 基本概念】C++编程三剑客:模板、多态与泛型编程的交织与差异
【C++ 基本概念】C++编程三剑客:模板、多态与泛型编程的交织与差异
104 0

热门文章

最新文章

相关实验场景

更多