首页 > 软件开发 > C++ > 正文
1.2.3 函数模板的默认模板参数
2015-07-07 13:47:47     我来说两句      
收藏    我要投稿

在C++98/03中,类模板可以有默认的模板参数,如下:

template <typename T, typename U = int, U N = 0>
struct Foo
{
   // ...
};

但是却不支持函数的默认模板参数:

template <typename T = int> // error in C++98/03: default template arguments
void func(void)
{
   // ...
}

现在这一限制在C++11中被解除了。上面的func函数在C++11中可以直接使用,代码如下:

int main(void)
{
   func();     // 如同一个普通的void(void)类型函数
   return 0;
}

从上面的例子中可以看出来,当所有模板参数都有默认参数时,函数模板的调用如同一个普通函数。对于类模板而言,哪怕所有参数都有默认参数,在使用时也必须在模板名后跟随“<>”来实例化。

除了上面提到的部分之外,函数模板的默认模板参数在使用规则上和其他的默认参数也有一些不同,它没有必须写在参数表最后的限制。

因此,当默认模板参数和模板参数自动推导结合起来使用时,书写显得非常灵活。我们可以指定函数中的一部分模板参数采用默认参数,而另一部分使用自动推导,比如下面的例子:

template <typename R = int, typename U>
R func(U val)
{
   ret val
}

int main(void)
{
   func(123);
   return 0;
}

但需要注意的是,在调用函数模板时,若显示指定模板的参数,由于参数填充顺序是从右往左的,因此,像下面这样调用:

func<long>(123); // func的返回值类型是long

函数模板func的返回值类型是long,而不是int,因为模版参数的填充顺序从右往左,所以指定的模版参数类型long会作为func的参数类型而不是func的返回类型,最终func的返回类型为long。这个细节虽然简单,但在多个默认模板参数和模板参数自动推导穿插使用时很容易被忽略掉,造成使用时的一些意外。

另外,当默认模板参数和模板参数自动推导同时使用时,若函数模板无法自动推导出参数类型,则编译器将使用默认模板参数;否则将使用自动推导出的参数类型。请看下面这个例子:

template <typename T>
struct identity
{
   typedef T type;
};

template <typename T = int>
void func(typename identity<T>::type val, T = 0)
{
   // ...
}

int main(void)
{
   func(123);   // T -> int
   func(123, 123.0);  // T -> double
   return 0;
}

在例子中,通过identity外敷模板禁用了形参val的类型自动推导。但由于func指定了模板参数T的默认类型为int,因此,在func(123)中,func的val参数将为int类型。而在func(123, 123.0)中,由于func的第二个参数123.0为double类型,模板参数T将优先被自动推导为double,因此,此时val参数将为double类型。

这里要注意的是,不能将默认模板参数当作模板参数自动推导的“建议”,因为模板参数自动推导总是根据实参推导来的,当自动推导生效时,默认模板参数会被直接忽略。

点击复制链接 与好友分享!回本站首页
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.2.2 模板的别名
下一篇:1.3 列表初始化
相关文章
图文推荐
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站