非类型函数模板参数

一、引入

你也可以为  function template 定义  nontype parameters。例如下面的  function template 定义了一组  函数,可以将参数  x  累加一个值(VAL)后传回: 

template <typename T, int VAL> 
T addValue(T const& x) { 
return x + VAL; 


当我们需要把「函数」或「某种通用操作」作为参数传递时,这一类函数就很有用。例如使用STL(Standard   Template   Library,标准模板库)时,你可以运用上述  function template 的实例(instantiation),将某值加到元素集内的每一个元素身上: 

std::transform (source.begin(), source.end(), //  来源端起止位置 
dest.begin(), //  目的端起始位置 
addValue<int,5>); //  实际操作 

最后一个自变量将  function template  addValue()实例化了,使其操作成为「将5加进一个int 数  值中」。算法transform()会对source  中的所有元素调用这个具现体(函数),然后把结果传入  dest  中。


注意上述例子带来的一个问题:addValue<int,5>  是个  function template  实体(instance),而我们知道,所谓「function templates  实体」被认为是命名了一组重载函数集,即使该函数集内可能只有一个函数。 根据目前标准, 编译器无法借助 「重载函数集」 来进行 template parameter 的推导。因此你不得不把  function template argument 强制转型为精确类型: 

std::transform (source.begin(), source.end(), //  来源端起止位置 
dest.begin(), //  目的端起始位置 
(int(*)(int const*)) addValue<int,5>); //  操作 
 
C++   Standard   中 已 有一 个提案 要 求修正这种行为 ,使你不必 在这种场合强制 转型。在尚未获得修正之前,为保证程序的可移植性,你还是得像上面那么做。 


二、局限性

注意,nontype template parameters 有某些局限:通常来说它们只能是常数整数(constant  integral values),包括  enum,或是「指向外部链接(external linkage)之对象」的指针。


以浮点数或  class-type objects  作为  nontype template parameters 是不可以的 

//  错误:浮点值不能作为  template parameters 

template <double VAT>
double process (double v) { 
return v * VAT; 

 

//  错误:class objects  不能作为  template parameters 

template <std::string name> 
class MyClass { 
... 
}; 
 
不允许浮点字面常数 (floating-point   literals) 或简单的常量浮点表达式 (constant   floating-point expressions)作为  template arguments,其实只是历史因素,并非技术原因。由于并没有什么实作上的困难,或许将来C++会支持它。 
 
由于字符串字面常数(string   literal)是一种采用内部链接(internal   linkage)的对象,也就是说不同模块(modules)内的两个同值的字符串字面常数,其实是不同的对象,因此它们也不能被拿来作为  template arguments: 
template <char const* name> 
class MyClass {  
... 
}; 
//  错误:不能使用字符串常量"hello" 

MyClass<"hello"> x; 
 
此外,全局指针也不能被拿来作为  template arguments: 
template  <char  const*  name> 
Class MyClass { 
... 
}; 
char const* s = "hello"; 
//  错误:s  是「指向内部链接(internal linkage)对象」的指针 
MyClass<s> x; 
 
但是你可以这么写: 
template  <char  const*  name> 
Class MyClass { 
... 
}; 
extern char const s[] = "hello"; 
MyClass<s> x; // OK 

全局的  char  array s  被初始化为   "hello",因此  s  是一个外部链接(external linkage) 对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值