C++11 可变模板参数
2017-07-06 11:07
441 查看
前言
C++11 增强了模板功能,在C++11之前,类模板和函数只能含有固定数量的模板参数,现在C++11中的新特性可变参数模板允许模板定义中包含0到任意个模板参数。可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面加上省略号“...”。其中的省略号的作用是:(1)声明一个参数包,这个参数包中可以包含0到人一个模板参数
(2)在模板定义的右边,可以将参数包展开成一个一个独立的参数
1. 可变参数模板
一个可变参数模板的定义是这样的template<class... T> void template_func(T... args)
{
cout << sizeof...(args) << endl;
}
template_func(1); //输出结果1
template_func(1, 2, 3); //输出结果3
template_func(1, 2, ""); //输出结果3从上面的例子可以看到,参数包可以容乃0到N个模板参数,这几个参数的类型可以任意的,在没有进行传参的时候,那么输出的结果就是0了。如果需要用参数包的参数,则一定要将参数包打开。有两种展开参数包的方法:
(1)通过递归的模板函数来实现参数包展开
(2)通过都好表达式和初始化列表方式展开参数包
1.1 递归函数方式展开参数包
通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止的函数,递归终止的函数正是用来终止递归的。//递归展开参数包
template<class Q, class... T> void template_func(Q head, T... args)
{
cout << "parameters:" << head << endl;
template_func(args...); //递归展开参数包
}
//递归的终止函数
void template_func()
{
cout << "end" << endl;
}
template_func(1, 2, 3, 4);上面有两个函数,一个是递归函数一个是递归终止函数,参数包args...在展开自己的过程中递归调用自己,没吊用一次参数包中的参数就会减少一个,知道所有的参数都展开为止,当没有参数的之后,就调用递归终止函数结束。
也可将上面的非模板函数写成模板函数
//递归展开参数包
template<class K, class... T> void template_func1(K head, T ...args)
{
cout << "parameters:" << head << endl;
template_func1(args...); //递归展开参数包
}
//递归的终止函数
template<class T> void template_func1(T t)
{
cout << t << endl;
}
template_func1(1,2,3,4);
1.2 逗号表达式和初始化列表方式展开参数包
递归函数展开参数包是一种标准做法,也比较好理解,但也存在一个缺点,就是必须要有一个重载的递归终止函数。使用逗号表达式和初始化列表就可以避免使用递归终止函数。//展开参数包
template<class... T> void template_func1(T ...args)
{
int array[] = {(my_print(args), 0)...};
}
template<class T> void my_print(T t)
{
cout << t << endl;
}
template_func1(1,2,3,4);
2. 可变参数模板消除重复代码
可变参数模板的一个特性是参数包中的模板参数可以是任意数量的和任意类型的,因此,可以以一种更加返回的方式去处理一些问题。下面是原始的创建对象工厂函数
template<typename T> T* Instance()
{
return new T();
}
template<typename T,typename T0> T* Instance(T0 arg0)
{
return new T(arg0);
}
template<typename T, typename T0, typename T1> T* Instance(T0 arg0, T1 arg1)
{
return new T(arg0, arg1);
}
template<typename T, typename T0, typename T1, typename T2> T* Instance(T0 arg0, T1 arg1, T2 arg2)
{
return new T(arg0, arg1, arg2);
}
struct A
{
A(int a)
{}
};
struct B
{
B(int a, int b)
{}
};
A* p_a = Instance<A>(1);
B* p_b = Instance<B>(1, 2);修改之后
struct A
{
A(int a)
{}
};
struct B
{
B(int a, int b)
{}
};
template<typename T, typename... args> T* Instance(args... arg)
{
return new T(arg...);
}
A* p_a = Instance<A>(1);
B* p_b = Instance<B>(1, 2);
相关文章推荐
- C 可变长参数 VS C++11 可变长模板
- C 可变长参数 VS C++11 可变长模板
- C 可变长参数 VS C++11 可变长模板
- C++11中可变参数个数的模板(variadic template)
- C++11 tuple & 可变模板参数
- C++11可变数量模板参数可变类型模板参数并使用lamada函数调用使用范例
- C++11:可变参数的模板
- c++11之可变模板参数
- C++11 可变模板参数例子
- C++可变参数的函数与模板实例分析
- C++11 新特性之 变长参数模板
- 让模板类支持可变模板参数
- 对于qt5的信号机制的一点参考,然后利用模板实现:在新线程执行可变函数参数的调用
- 让模板类支持可变模板参数(不定个数的参数)
- 通用模板实现可变参数函数
- 编写可变参数函数模板
- C++11标准——变长参数模板
- C++11 引用叠加规则和模板参数类型推导规则
- 【c++11】变长参数模板
- C++ 11可变参数接口设计在模板编程中应用的一点点总结