C++11 可变参数模板

在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
时间: 2024-10-25 10:31:52

C++11 可变参数模板的相关文章

c++11——可变参数模板

在c++11之前,类模板和函数模板只能含有固定数量的模板参数,c++11增加了可变模板参数特性:允许模板定义中包含0到任意个模板参数.声明可变参数模板时,需要在typename或class后面加上省略号"...".     省略号的作用有两个: 1. 声明一个参数包,这个参数包中可以包含0到任意个模板参数 2. 在模板定义的右边,可以将参数包展开成一个一个独立的参数 1. 可变参数模板函数 可变参数模板函数的定义如下: template<class... T> void f

C++ 11可变参数接口设计在模板编程中应用的一点点总结

概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量(或属性,C#中属性和成员变量还是有区别的): 类的成员方法: 从编译器的角度看,我们必须明确指定以上3部分,才算完整地定义了一个类并且编译通过. 所谓的“类弱化”,是指类的设计者在定义类的时候,并没有完整定义一个类,而是把类的其中一部分的定义留给类的使用者. 从传统才c++98看,通过模板类,使用

函数模板,函数模板重载,可变参数模板,函数模板覆盖,通过引用交换数据

 1.函数模板初级,如果想使用模板,需要实例化,实例化的方式是加上<数据类型> #include <iostream> //函数模板可以对类型进行优化重载,根据类型会覆盖 //如果仍然要使用模板函数,需要实例化 template<class T> T add(T a, T b) { std::cout << "T add " << std::endl; return a + b; } int add(int a, int

c++ --可变参数模板

一个可变参数模板就是一个可接受可变数目参数的模板函数或模板类. 可变数目的参数被称为参数包. 1 //可变参数模板;sizeof ...()运算符 2 template <typename ... Args> 3 void g(Args ... args) 4 { 5 cout<<sizeof ...(Args)<<endl; //类型参数的数目 6 cout<<sizeof ...(args)<<endl; //函数参数的数目 7 } 8 9

C++中的可变参数模板

作者:Eli Bendersky http://eli.thegreenplace.net/2014/variadic-templates-in-c/ 回到C++11前夜,编写带有任意参数函数的唯一办法是使用可变参数函数,像printf,使用省略号语法(-)以及伴随的va_族的宏.如果你曾经使用这个方法编写代码,你会知道这有多累赘.除了变成类型不安全外(所有的类型解析必须在运行时在va_arg里通过显式转换来完成),要做对并不容易.Va_宏执行低级的内存操作,我看见过许多因为没有小心使用它们导致

求变量的数据类型,typeid,bool,C和C++的不同,new和delete,C++中的枚举,inline和可变参数模板,auto和函数模板,宽字符

求变量的数据类型,通过函数typeid(变量名).name();获得变量的数据类型. 案例如下: #include <iostream> #include <stdlib.h> void main() { double db = 10.9; double *pdb = &db; auto num = pdb; //通过typeid的方式获得数据类型 std::cout << typeid(db).name() << std::endl; std::c

C++11新特性之五——可变参数模板

有些时候,我们定义一个函数,可能这个函数需要支持可变长参数,也就是说调用者可以传入任意个数的参数.比如C函数printf(). 我们可以这么调用. printf("name: %s, number: %d", "Obama", 1); 那么这个函数是怎么实现的呢?其实C语言支持可变长参数的. 我们举个例子, double Sum(int count, ...) { va_list ap; double sum = 0; va_start(ap, count); fo

可变参数模板

一.基本语法 声明一个带有可变参数个数的模板的语法如下所示: template<typename ...Element> class tuple; tuple<int, string> a;  // use it like this 在模板参数 Element 左边出现省略号 ... ,就是表示 Element 是一个模板参数包(template type parameter pack).parameter pack(参数包)是新引入 C++ 中的概念,比如在这个例子中,Eleme

C++11中的Tuple和可变参数模版

C++11中的tuple是一个n元的可变元组,它相当于有n个元素的结构体,只不过这个结构体的成员都是匿名的,tuple中提供了一个get()方法来获取某个下标对应的元素的值.另外可以通过make_tuple()方法来构造一个tuple对象.具体用法如下 我们知道tuple中的元素个数是不确定的,而每个元素的类型通过模板参数指定,那么tuple是如何做到这些的呢?答案就是使用可变参数模板.在C++中,我们使用过printf函数,它的参数就是可变的,在C++11中也允许模板的参数也是可变的.举个例子