C++11 函数模板的默认模板参数

类模板:通用的类描述(使用泛型来定义类),进行实例化时,其中的泛型再用具体的类型替换。

函数模板:通用的函数描述(使用泛型来定义函数),进行实例化时,其中的泛型再用具体的类型替换。

【1】C++98标准中两者的区别

函数模板和类模板在C++98标准中一起被引入,两者区别主要在于:

在类模板声明时,标准允许其有默认模板参数。而函数模板却不支持。

默认模板参数的作用如同函数的默认形参。不过在C++11中,这一限制已经被解除了,如下例所示:

1 void DefParm(int m = 3) {} // c++98编译通过,c++11编译通过
2
3 template <typename T = int>
4 class DefClass {};        // c++98编译通过,c++11编译通过
5
6 template <typename T = int>
7 void DefTempParm() {};    // c++98编译失败,c++11编译通过

可以看到,DefTempParm函数模板拥有一个默认模板参数(类型int)。

使用仅支持C++98的编译器编译,DefTempParm的编译会失败,而支持C++11的编译器则无问题。

【2】C++11标准中两者的区别

尽管C++11支持了函数模板的默认模板参数,不过在语法上,两者还是存在区别:

类模板在为多个默认模板参数声明指定默认值时,必须遵照“从右往左”的规则进行指定。

而这个规则对函数模板来说并不是必须的。示例如下:

 1 template <typename T1, typename T2 = int>
 2 class DefClass1 {};
 3
 4 template <typename T1 = int, typename T2>
 5 class DefClass2 {};  // ERROR: 无法通过编译:因为模板参数的默认值没有遵循“由右往左”的规则
 6
 7 template <typename T, int i = 0>
 8 class DefClass3 {};
 9
10 template <int i = 0, typename T>
11 class DefClass4 {};  // ERROR: 无法通过编译:因为模板参数的默认值没有遵循“由右往左”的规则
12
13 template <typename T1 = int, typename T2>
14 void DefFunc1(T1 a, T2 b) {}; // OK 函数模板不用遵循“由右往左”的规则
15
16 template <int i = 0, typename T>
17 void DefFunc2(T a) {};  // OK 函数模板不用遵循“由右往左”的规则

可以看到,不按照从右往左定义默认类模板参数的模板类DefClass2和DefClass4都无法通过编译。

而对于函数模板来说,默认模板参数的位置则比较随意。

DefFunc1和DefFunc2都为第一个模板参数定义了默认参数,而第二个模板参数的默认值并没有定义,C++11编译器却认为没有问题。

函数模板的参数推导规则也并不复杂。简单地讲:如果能够从函数实参中推导出类型的话,那么默认模板参数就不会被使用,反之,默认模板参数则可能会被使用。

如下示例:

 1 template <class T, class U = double>
 2 void f(T t = 0, U u = 0) {};
 3 void g()
 4 {
 5     f(1, ‘c‘); // f<int, char>(1, ‘c‘)
 6     f(1);      // f<int, double>(1, 0), 使用了默认模板参数double
 7     f();       // 错误: T无法被推导出来
 8     f<int>();  // f<int, double>(0, 0), 使用了默认模板参数double
 9     f<int, char>(); // f<int, char>(0, 0)
10 }

定义了一个函数模板f,f同时使用了默认模板参数和默认函数参数。

可以看到,由于函数的模板参数可以由函数的实参推导而出:

在f(1)这个函数调用中,实例化出了模板函数的调用应该为f<int, double>(1, 0),其中,第二个类型参数U使用了默认的模板类型参数double,而函数实参则为默认值0。

类似地,f<int>()实例化出的模板函数第二参数类型为double,值为0。

而表达式f()由于第一类型参数T的无法推导,从而导致了编译的失败。

而通过这个例子也可以看到,默认模板参数通常是需要跟默认函数参数一起使用的。

还有一点应该注意:模板函数的默认形参值不是模板参数推导的依据。函数模板参数的选择,终究是由函数的实参推导而来的。

good good study, day day up.

顺序 选择 循环 总结

原文地址:https://www.cnblogs.com/Braveliu/p/12231451.html

时间: 2024-10-14 18:33:14

C++11 函数模板的默认模板参数的相关文章

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

 1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel> template<class T> class run { public: T w; void show() { w.show(); } void settext() { w.setText("A"); }

C++11 新特性之 变长参数模板

template <typename ... ARGS> void fun(ARGS ... args) 首先明确几个概念 1,模板参数包(template parameter pack):它指模板参数位置上的变长参数,例如上面例子中的ARGS 2,函数参数包(function parameter pack):它指函数参数位置上的变长参数,例如上面例子中的args 一般情况下 参数包必须在最后面,例如: template <typename T, typename ... Args>

函数模板,函数模板重载,可变参数模板,函数模板覆盖,通过引用交换数据

 1.函数模板初级,如果想使用模板,需要实例化,实例化的方式是加上<数据类型> #include <iostream> //函数模板可以对类型进行优化重载,根据类型会覆盖 //如果仍然要使用模板函数,需要实例化 template<class T> T add(T a, T b) { std::cout << "T add " << std::endl; return a + b; } int add(int a, int

函数模板和类模板

一.函数模板 函数模板代表一类相同结构的函数,通过用户提供的具体参数,C++编译器在编译时刻能够将函数模板实例化,根据同一个模板创建出不同的具体函数,这些函数之间的不同之处主要在于函数内部一些数据类型的不同. 1 #include "stdafx.h" 2 #include <iostream> 3 using namespace std; 4 5 template <typename T> 6 T max1(T a,T b) 7 { 8 return a>

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始

C++学习之模板 ----函数模板、类模板

本博文主要讨论函数模板与类模板以及其简单应用. 1).作用:函数模板和类模板都可以看做是一种代码产生器,往里面放入具体的类型,得到具体化的函数或者class. 2).编译(分为两步): a):实例化之前,先检查模板本身语法是否正确: b):根据 函数调用或者类模板调用 ,先去实例化模板代码,产生具体的函数/类. 也就是说, 没有函数调用或者类类型对象声明,就不会实例化模板代码,在目标文件obj中找不到模板的痕迹. 3):优缺点 模板的缺点是代码膨胀,编译速度慢,而优点是运行速度快. 一.函数模板

C++模板之可变模板参数

可变模板参数---- C++11新特性 可变模板参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数.任意类型的参数 由于可变模版参数比较抽象,使用起来需要一定的技巧,所以它也是C++11中最难理解和掌握的特性之一 参数包(parameter pack) 模板参数包,如: template<typename- Args>class tuple; Args标识符的左侧使用了省略号,在C++11中Args被称为"模板

[C++] 用Xcode来写C++程序[5] 函数的重载与模板

用Xcode来写C++程序[5] 函数的重载与模板 此节包括函数重载,隐式函数重载,函数模板,带参数函数模板 函数的重载 #include <iostream> using namespace std; int operate (int a, int b) { return (a * b); } double operate (double a, double b) { return (a / b); } int main () { int x = 5; int y = 2; double n

函数模板与类模板

函数模板,顾名思义,是在生成函数时依照的模板. 有时,我们需要对不同的数据类型做同样的函数操作. 比如:分别对一个int类型数 和 一个double类型数求平方. 这时,虽然都是同样的求平方操作(函数体内代码一样),但是我们必须要编写两个不同的函数,因为处理int类型的函数的参数和返回值类型都应该是int,而处理double类型的函数的参数和返回值都应该是double. 如下:函数体内操作代码一样,设计为重载函数,用相同的函数名,但是参数类型和返回值类型却都不一样,函数需要定义两次. int S