码迷,mamicode.com
首页 > 编程语言 > 详细

C++11 可变参数模板

时间:2016-06-06 09:03:09      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

在C++11之前, 有两个典型的受制于模板功能不强而导致代码重复难看的问题, 那就 function object 和 tuple。 拿 function objects 来说, 需要一个返回类型参数及N个参数类型参数。 但因为变长参数模板不受支持,导致不得不重复书写7、8个模板类,但最终也只能支持7、8个参数的 function object。C++11中最终为我们带来了强大的变长 参数模板功能,这些问题也随之迎刃而解了。 

可变参数模板(Variadic Template)故名思义,即可以接受任意数量参数的类/函数模板。 其声明方式为

template<typename... Args>
class VariadicTemplate;

当然non-type参数也是支持的比如 template<int... Args> class VariadicIntTemplate;

这里Args代表0-N个类型参数,也就是说VariadicTemplate<>也是有效的模板实例。

C++11 翻新了省略号(...)操作符来支持对这种模板参数的访问及使用。

类型展开

将所有模板参数展开在当前位置,用来调用其它模板、声明函数指针类型

技术分享
template<typename ...Args>
int foo() {
    int (*p)(Args...) = bar<Args...>;
    p(1, 0.5);
    return bar<Args...>(1, 0.5); 
}
技术分享

对于 foo<int, float> 实例,其 p 的类型为 int (*)(int, float) 而 return 语句将调用 bar<int, float>(1, 0.5)

此外还可以展开类型参数用来指定基类列表

template<typename... Args>
class foo : Args...{
};

foo<bar, barz> f; // 该类继承 bar, barz 两个基类

Parameter Packs / Initialization Lists

通过省略号操作符可以声明参数包,这些参数包可以在函数的参数位置展开。

template<typename ...Args>
void foo(Args... args) {
}

当使用 foo<int, float> 时,其有两参数,一个整数,一个float,因此调用方法为 foo<int, float>(1, 0.1f);

此外还可以将参数包展开到构造函数的初始化列表

技术分享
template<typename... Args>
class foo : Args...{
public:
    foo(Args...args):Args(args)...{
    }
};

foo<bar, barz> f(bar(), barz());
技术分享

sizeof... operator

要获取模板变长参数的实参长度,使用 sizeof... 运算符,它也可以被用于 Parameter Packs

技术分享
template<typename ... Args>
size_t foo() {
    return sizeof...(Args);
}
template<typename ... Args>
size_t fooz(Args ...args) {
    return sizeof...(args);
}
技术分享

以上就是变长参数的基本用法,但真正发挥作用,往往还要借助模板特化 (Template Specialization)

可变参数模板与模板特化

可变参数模板与普通模板一样,可以进行特化,从而实现一些有意义的模式

技术分享
template<typename ... Args>
void output(Args ... args) {
}
template<typename Arg0, typename ... Args>
void output(Arg0 arg0, Args ... args) {
    std::cout << arg0;
    output<Args...>(args...);
}
template<>
void output() {
}

/*------------------------------*/
typedef decltype(std::cout) cout_type;
auto endl = std::endl<cout_type::char_type, cout_type::traits_type>;
output(1, 0.3, (void*)nullptr, "string", c, endl);
技术分享

以上代码输出

10.30stringc

C++11 可变参数模板

标签:

原文地址:http://www.cnblogs.com/shouce/p/5562664.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!