现在的位置: 首页 > 综合 > 正文

关于函数模板参数的问题

2012年11月28日 ⁄ 综合 ⁄ 共 2153字 ⁄ 字号 评论关闭

 

c++模板学习笔记(之二)

——关于函数模板参数的问题

 

/*-----------------------------------------------------------------------------------

欢迎评论和转载,转载请注明出处:http://blog.csdn.net/lingyin55

------------------------------------------------------------------------------------*/

如果没有特别说明,以下程序的运行环境都为vs2008

 

对于function template来说,有两种参数:

一、template parameters(模板参数),如下:

template <typename T>

 

二、call parameters(调用参数),在function
template
后说明,如下:

/*前面可能有返回类型*/
max (T const& a, T const& b);

 

下面先给出一个简单的例子,然后再一步一步来讨论可能出现的问题及解决办法,如下:

 

template <
typename T1,
typename T2 >

inline T1 max(
const T1& a,
const T2& b )

{

return a < b ? b : a;

}

 

int main()

{

max( 4, 5 );

return 0;

}

 

max的作用不用多言,那么上面的程序有什么特别需要注意的呢?

一、注意到类型T1T2被定义成不同类型(当然,如果传入类型相同也可),这样有个好处,对于不同类型的值可以调用该函数模板,如max(4,4.1);一个整型和一个浮点型。这里有个地方要说明,并不是对于任意的类型都可以传入调用,原因很简单,传入的类型如果不同,必须满足其中一种类型通过隐式转换可以转成另外一种类型,否则出错。如max(4,”hello”);//出错

 

二、function template不能有默认模板参数,如下则报错

 

int c = 10;//定义一个变量,用于作为T2的默认值

 

//b设定一个默认参数

template <
typename T1,
typename T2 >

inline T1 max(
const T1& a,
const T2& b = c )

{

return a < b ? b : a;

}

 

int main()

{

//调用时出错,提示无法为T2进行类型推导

max( 4 );

return 0;

}

 

其中第二个参数用了默认参数,结果编译器提示错误“could not deduce template
argument for 'T2'”
。这点也class template不同,在class
template
中允许传入默认参数(class template后续讨论)。

 

三、对于上面的程序,不能以引用的(by
reference
)的方式返回值。如把程序改为

 

template <
typename T1,
typename T2 >

inline
const T1& max(
const T1& a,
const T2& b )

{

return
a < b ? b : a;

}

 

int main()

{

std::cout << max( 4, 5.2 ) << std::endl;

return 0;

}

 

输出是5,但程序是有问题的,因为返回值类型是int,对于5.2(编译器认为是double型),编译器会强制转换为int5(此时编译器会有警告,提示从double转为int会导致精度的丢失),并用一个int的临时变量来保存返回的结果,最后将这个临时变量返回。我们知道,当函数的作用域结束时,临时变量会被释放掉,因此返回临时变量的引用或者地址(其实道理一样),都是不明智的,因此上面的程序只能返回T1,而不能返回T1&

当然,如果类型相同,如max( 4, 5)都为整型,则不会出现上面的问题,但此时何不把T1T2定义为相同的类型呢?如
inline
const T& max(
const T& a,
const T& b )
。实际上,为了保持代码的简单,推荐的做法便是尽量将函数模板的类型定义为相同的,即【单一类型】。

 

四、或许已经有人想到,其实可以再定义一个类型作为函数模板的返回类型,如下的RT

template<typename
T1,
typename T2,
typename RT>

inline
const RT& max(
const T1& a,
const T2& b );

 

但是请先明白,函数模板对于参数的推导,仅仅限于传入的调用参数,对于返回值的类型,推导机制并不会对其与返回值进行匹配,因此编译器无法推导出RT

怎么办呢?既然编译器无法自己推导,那我们可以明确指定啊!因此对于上面的函数模板,我们可以使用这种方法调用max<int,double,double>(4,
5.2);<>
中的第三个类型对应于返回类型RT

 

为了少写一点参数,其实可以对模板中声明的类型顺序改变一下,因为函数模板的调用参数(call
parameters)
还是可以利用编译器自己去推导的,改后的声明如下

template<typename
RT,
typename T1,
typename T2>

inline
const RT&
max(
const
T1& a,
const
T2& b );

调用方式max<double>(4,
5.2);
//
只需声明函数的返回类型是double

 

抱歉!评论已关闭.