C++模板:实参演绎

在C++函数模板中,实参演绎是一非常种灵活的机制,实参演绎的字面意思就是:通过实参的类型来推断函数模板的类型参数,举个简单的函数模板的例子:

template<typename T>
T& func1(T  &a,  T &b) {
	cout<<typeid(T).name()<<endl;
}

因为有了实参演绎,我们可以像使用普通函数一样来使用模板函数,如下:

int a,b;
func1(a,b);

也就是说,虽然我们没有为func指定T,编译器也可以通过a、b的类型来推断出T是什么,这里T被推断成了int。实参演绎的意图是很容易理解的,只是有一些细节需要额外的注意,现在给出另外一个模板:

template<typename T>
T & func2(T  a,  T b) {
	cout<<typeid(T).name()<<endl;
}

这个函数模板使用T a替换掉了T& a,会带来什么影响呢?取决于实参是什么,如果实参是基本类型,像上面的int a, b,那么使用func2时,推断出来的T也是int,然而如果实参是数组,func1和func2就有区别了,简单验证一下:

int a[2],b[2];
func1(a,b);
func2(a,b);

输出的结果是:在func1中,T被推断成了int*,而在func2中,T被推断成了int [2]。如果我们把func1、func2糅合一下,像下面的func3一样,会发生什么情况呢?

template<typename T>
T & func3(T a,  T &b) {
	cout<<typeid(T).name()<<endl;
}

这时如果继续使用func3(a,b),就会出现如下的编译错误:

error: no matching function for call to ‘func3(int [2], int [2])’

因为在实参演绎中,根据a推断出T为int*(发生了decay),而根据b推断出T为int [2],这二者是不一致的,所以会出错(因为在func3的函数模板定义中中,a、b应该是相同类型的)。这样的错误也可能发生在其他一些情况,如:

int const a;
int const b;
func3(a,b);

这时编译器会输出类似的错误:error: no matching function for call to ‘func3(int&, const int&)’,因为func1函数模板会忽略const,而func2函数模板不会,volatile也是一样,再比如:

void f1() {};
void f2() {};
func1(f1,f2);
func2(f1,f2);
func3(f1,f2);

func1(f1,f2)是没有问题的,T被推断成了函数指针(发生了decay),func2(f1,f2)也没问题,T被推断成了无参且返回类型为空的函数类型,而func3(f1,f2)就不能通过编译,也会出现no matching的错误。

时间: 2024-10-13 04:14:07

C++模板:实参演绎的相关文章

C++ template —— 实例化和模板实参演绎(四)

本篇讲解实例化和模板实参演绎------------------------------------------------------------------------------------------------------------第10章 实例化------------------------------------------------------------------------------------------------------------模板实例化是一个过程,它

模板实参演绎

一.什么是实参演绎 如果我们每次都必须显式的指明模板替换参数类型,例如concat<std::string, int>(s, 3),那么过程将会显得非常繁琐. 如果我们可以concat(s, 3)//之前必须声明s是std::string类型,那么将会向普通的函数调用一样简单, 事实上,C++是允许这样的写法,然后C++编译器会根据实参(s和3)的类型推算出合适的替换类型. 如何演绎? 1 template<typename T> 2 T const& max(T cons

template_11实参演绎

1,演绎过程匹配类型A(来自实参的类型),参数化类型P(行参参数声明)如果被声明的参数是一个引用声明g(T& )那么P就是所引用类型T:f(T)中P就是所声明的参数类: decay指从数组和函数类型隐式转换为指针类型.如果实参的类型是数组或函数类型,则会发生decay,此时还会忽略高层次的const和volatile限定符. template <class T>T const& max(T const& a, T const& b) T被要求同时是char[7]

C++模板实参推断

1 类型转换与模板实参 1)自动转换的只有:const转换, 数组及函数到指针的转换 注:不同大小相同元素类型是不同的类型 2)相同模板参数名对应的实参类型必须相同 3)不同模板参数名对应的实参类型可以不同,但必须兼容 2 函数模板的返回值问题 函数模板只会对函数参数列表的类型进行推断不会对返回值推断 解决方法: 1) 显示模板参数 注: 显示指定了模板类型参数在类型转换上和普通函数参数一样 template <typename T1, typename T2, typename T3> T1

[014]模板-模板实参推导

对于函数模板,编译器利用调用中的函数实参来确定其函数模板,从函数实参来确定模板实参的过程就被叫做是模板实参推导. 比如: 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 template <class T> 6 int compare(const T &v1, const T &v2) { 7 if (v1 > v2) { 8 cout << &quo

C++ primer-&gt;16.2 模板实参推断

一.类型转换与模板类型参数 1.如果一个函数形参的类型使用了模板类型参数,那么它采用特殊的初始化规则.只有很有限的几种类型转换会自动地应用于这些实参. ①.顶层const无论是在形参中还是在实参中,都会被忽略. ②.const转换:可以将一个非const对象的引用(或指针)传递给一个const的引用(或指针)形参. ③.数组或函数指针转换:如果函数形参不是引用类型,则可以将对数组或函数类型的实参应用于正常的指针转换. 如下程序所示: 1 template<typename T> T fobj(

【C++ Primer 第16章】2. 模板实参推断

模板实参推断:对于函数模板,编译器利用调用中的函数实参来确定模板参数,从函数实参来确定模板参数的过程被称为模板实参推断. 类型转换与模板类型参数 与往常一样,顶层const无论在形参中还是在是实参中,都被会忽略. • const转换:可以将一个非const对象的引用(或指针)传递给const的引用(或指针)形参. • 数组或函数指针转换:一个数组实参可以转换为一个指向其首元素的指针.类似的,一个函数实参可以抓转换一个该函数类型的指针. 1 template <typename T> T fob

模板与泛型编程——模板实参推断

一.模板实参推断 对于函数模板,编译器利用调用中的函数实参来确定其模板参数.从函数实参来确定模板实参的过程被称为模板实参推断.在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数与给定的函数调用最为匹配. 1.类型转换与模板类型参数 与非模板函数一样,我们在一次调用中传递给函数模板的实参被用来初始化函数的形参.如果一个函数形参的类型使用了模板类型参数,那么它采用特殊的初始化规则.只有很有限的几种类型转换会自动地应用于这些实参.编译器通常不是对实参进行类型转

C++11 局部和匿名类型作模板实参

[1]C++11支持局部的类型和匿名类型做模板的实参 在C++98中,标准对模板实参的类型还有一些限制. 具体地讲,局部的类型和匿名的类型在C++98中都不能做模板类的实参. 而在C++11标准中,支持做模板的实参.示例如下: 1 template<typename T> class X {}; 2 template<typename T> void TempFun(T t) {}; 3 4 struct A { } a; 5 struct { int i; } b; // b是匿