Introduction:

Before the possibilities of the new C++ language standardC++11, the use of templates was quite limited when it came to implementing for instance function objects (functors) & tuple facilities. Implementing these sort of things using earlier C++ standard often require similiar code to be repeated various times without forgetting preprocessor metaprogramming. However, thanks to variadic templates, programming new features using templates has become easierclearer & more memory-efficient.

Although the D programming language also provides the use of variadic templates, only variadic templates offered by C++11 standard will be covered here, so knowledge of D programming language's variadic templates is not required in order to read & understand this article. There are assumptions, however, that the reader of this article understands what class & function templates are & how to declare, define & use them.

 What is a variadic template?

Variadic template is a template, which can take an arbitrary number of template arguments of any type. Both the classes & functions can be variadic. Here's a variadic class template:

1
2
template<typename... Arguments>
class VariadicTemplate;
 

Any of the following ways to create an instance of this class template is valid:

1
2
3
VariadicTemplate<double, float> instance;
VariadicTemplate<bool, unsigned short int, long> instance;
VariadicTemplate<char, std::vector<int>, std::string, std::string, std::vector<long long>> instance;
 

The number of variadic template arguments can also be zero, so the following

VariadicTemplate<> instance;

is also valid C++11.

However, if you create a template like this:

1
2
template<typename T, typename... Arguments>
class VariadicTemplate;
 

You must set at least one type as a template argument (for typename T), unless default type has been initilialized, like in the following declaration:

1
2
template<typename T = int, typename... Arguments>
class VariadicTemplate;
 

 Syntax - the ellipsis operator (...):

The ellipsis operator (...) is an operator used in different contexts in C++. It's name comes from an ellipsis mechanism in C. In this mechanism programmer can create a function taking variable number of parameters. Probably the most famous function in both C & C++ to take advantage of this mechanism is printf-function in C standard library:

int printf (const char* format, ... );

Ellipsis mechanism can also be used with preprocessor in a form of a macro. A macro taking a variable number of parameters is called a variadic macro.

#define VARIADIC_MACRO(...) 

In C++, this ellipsis operator got a new meaning in different context called exception handling. The operator is used in catch blocks after try blocks:

1
2
3
4
5
6
try{
// Try block.
}
catch(...){
// Catch block.
}
 

Here, the ellipsis operator indicates that the catch block takes in any exception thrown from the try block as it's parameter, no matter the type.

In C++11, variadic templates brought yet another meaning for this operator. The operator works somewhat like in ellipsis mechanism as already stated, but it's bit more complex:

1
2
template<typename... Arguments>
void SampleFunction(Arguments... parameters);
 

Here's a function template. The contents of the variadic template arguments are called parameter packs. These packs will then be unpacked inside the function parameters. For example, if you create a function call to the previous variadic function template...

SampleFunction<intint>(16, 24);

...an equivalent function template would be like this:

1
2
template<typename T, typename U>
void SampleFunction(T param1, U param2);
 

 Syntax - the sizeof... operator (sizeof...):

Another operator used with variadic templates is the sizeof...-operator. Unlike the sizeof operator, which can be used to determine the size of a type (for example sizeof(int) or sizeof(double)), sizeof... operator can be used to determine the amount of types given into a variadic template. This can be achieved like this:

1
2
3
4
5
template<typename... Arguments>
class VariadicTemplate{
private:
static const unsigned short int size = sizeof...(Arguments);
};
 

 Syntax - two ellipsis operators together (......):

In some circumstances, there can be two ellipsis operators put together (......). These two operators can also be separated (written as ... ...).

Probably the most clear way, however, is to separate these two operators with a comma (..., ...). Both ways with a comma or without a comma are acceptable.

This kind of syntax can appear with variadic function templates using ellipsis mechanism:

1
2
3
4
template<typename... Arguments>
void SampleFunction(Arguments......){ }
 

As already stated, these two ellipsis operator put together can be written differently, so the following examples

1
2
3
4
template<typename... Arguments>
void SampleFunction(Arguments... ...){ }
 
1
2
3
4
template<typename... Arguments>
void SampleFunction(Arguments..., ...){ }
 

work as well.

 Author's opinions & thoughts: For the sake of readability, use the last method to mark the two following ellipsis operators. The previous alternatives may be found confusing and/or cumbersome. Some may find it a matter of taste, though.

 Uses of variadic templates - inheritance & initialization lists:

When it comes to classes, variadic templates can be used with inheritance & initialization lists. Inheritance taking advantage of variadic templates can be accomplished like this:

1
2
template<typename... BaseClasses>
class VariadicTemplate : public BaseClasses...
 

And, if we want to create a constructor inside this class using initialization list to call the constructors of all the given base classes as template arguments, we'd have to do it this way:

1
2
3
4
5
6
7
template<typename... BaseClasses>
class VariadicTemplate : public BaseClasses...{
public:
VariadicTemplate(BaseClasses&&... base_classes) : BaseClasses(base_classes)...{ }
};
 

As you can see there's a new operator introduced in C++11 in the constructor's parameter list - an rvalue operator (&&), which allows rvalue references. This article is not intended to cover the use of this operator, but for information how to use this operator (& rvalue references in general), please follow this link:
http://thbecker.net/articles/rvalue_references/section_01.html

 Uses of variadic templates - variadic class template specialization:

Like class templates, variadic class templates can also be specialized. With templates, the specialization happens like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename T>
class Template{
public:
void SampleFunction(T param){ }
}; template<>
class Template<int>{
public:
void SampleFunction(int param){ }
};
 

But with variadic templates it's like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename... Arguments>
class VariadicTemplate{
public:
void SampleFunction(Arguments... params){ }
}; template<>
class VariadicTemplate<double, int, long>{
public:
void SampleFunction(double param1, int param2, long param3){ }
};
 

 Caution: Some compilers may not support variadic class template specialization yet, or their implementation may be somewhat incomplete.

 See also:

If you are interested in seeing a C++11 standard class template utilizing variadic templates, please take a look at already mentioned tuple from the link below:
http://www.cplusplus.com/reference/std/tuple/tuple/

Another field where variadic templates may come in handy is delegates. If you are already familiar with managed C++ and/or C#, picking up C++ delegates may not be a problem. You might find good use for them in C++ anyway.

C++11 : variadic templates(可变参数模板)的更多相关文章

  1. 【C/C++】C++11 Variadic Templates

    Variadic Templates 1.function template:利用“参数个数逐一递减”的特性,实现递归函数调用 template <typename T, typename... ...

  2. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  3. 泛化之美 —— C++11 可变参数模板的妙用

    概述 首先这篇文章出自博客园作者:[qicosmos ],我对本文的实例代码进行了学习.思考和整理纠正,理清了文章的全部细节,觉得这是一篇让我受益匪浅的文章.之所以会接触「可变参数模板」这部分的内容, ...

  4. c++11 可变参数模板类

    c++11 可变参数模板类 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...

  5. c++11 可变参数模板函数

    c++11 可变参数模板函数 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #in ...

  6. C++反射机制:可变参数模板实现C++反射

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在Github ...

  7. 第27课 可变参数模板(8)_TupleHelper

    1. TupleHelper的主要功能 (1)打印:由于tuple中的元素是可变参数模板,外部并不知道内部到底是什么数据,有时调试时需要知道其具体值,希望能打印出tuple中所有的元素值. (2)根据 ...

  8. 第25课 可变参数模板(6)_function_traits和ScopeGuard的实现

    1. function_traits (1)function_traits的作用:获取函数的实际类型.返回值类型.参数个数和具体类型等.它能获取所有函数语义类型信息.可以获取普通函数.函数指针.std ...

  9. C++11_ Variadic Templates

    版权声明:本文为博主原创文章,未经博主允许不得转载. 这次主要介绍C++11的又一个新特性 Variadic Templates (可变模板参数) 它的实现类似于initializer_list< ...

随机推荐

  1. vs2013+sql server2012 +win8.1+entity framework + linq

    项目右键添加类选择“ADO.NET实体数据模型” 选择“空……” 项目会自动产生后缀.edmx的文件(ModelTest.edmx),会自动添加引用System.Runtime.Serializati ...

  2. 武汉科技大学ACM :1009: 华科版C语言程序设计教程(第二版)习题6.11

    Problem Description n个人围成一圈,依次从1至n编号.从编号为1的人开始1至k报数,凡报数为k的人退出圈子,输出最后留下的一个人原来的编号. Input 首先输入一个t,表示有t组 ...

  3. 常用CSS代码片断

    单行文本截字 .nowrap { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; word-break: normal; ...

  4. JQuery连接地址

    <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> http://co ...

  5. Python3 如何优雅地使用正则表达式(详解四)

    更多强大的功能 到目前为止,我们只是介绍了正则表达式的一部分功能.在这一篇中,我们会学习到一些新的元字符,然后再教大家如何使用组来获得被匹配的部分文本. 更多元字符 还有一些元字符我们没有讲到,接下来 ...

  6. Spring碎点知识

    1.依赖注入:不仅可以为Bean注入普通的属性值,还可以注入其他Bean的作用.通过配置文件组织在一起,这里的Bean是Java对象 说明:关于依赖注入与控制反转的这两个名字,表达的都是同一个意思,只 ...

  7. iOS-OC命名规范

    IOS开发(OC)中的命名规范 正文:通过读写大量代码我有自己的一套编程思路和习惯,自认为自己的编码习惯还是不错的,代码结构也算清晰,因为我一直以来都是代码看的多写的多,但是总结的比较少,知识经常不成 ...

  8. SJA1000寄存器设置

    在设置CAN控制器SJA1000的输出控制寄存器(OCR)时,由于电路图中只用到了TX0和RX0,所以只考虑OCTP0,OCTN0,OCPOL0.这里设置成了010.然后查了一下配置的表,如下所示: ...

  9. Fireworks Extension —— 开发篇(Dom模型)

    如上一篇博文所叙述的,一个很偶然的机会,我得知可以使用Javascript开发Fireworks插件,又注意到了视觉小伙伴的需求,于是便上手开发Fireworks Extension了. 很幸运的,在 ...

  10. Android UI 调试常用工具(Dump view UI hierarchy for Automator)

    UI调试时程序员比较头疼的问题:有时候经常会被1dp.2dp的问题,搞得无言以对(Android开发深有体会) 下面介绍一个在实际开发过程中常用的一个调试工具,可以精确到每个View在屏幕中的绝对位置 ...