版权声明:本文为博主原创文章,未经博主允许不得转载。

这次主要介绍C++11的又一个新特性 Variadic Templates (可变模板参数)

它的实现类似于initializer_list<>,它可是使类模板接受一包参数

本节主要应用递归的形式介绍 Variadic  Templates

1.简单的调用

#include <iostream>
#include "string" using namespace std; void printX() {}//为了响应最后一次printX()的调用,因为这次没有传递参数,如果不声明不带参数的函数会报错 template <typename T, typename... Types>
void printX(const T& firstArg, const Types&... args)
{
cout<<firstArg<<endl;
printX(args...);//递归调用
} int main()
{
printX(,,);
return ;
}

输出结果

第一次调用printX()时传递的参数为(1,一包参数) 此时输出1 ,然后递归调用printX(args...)

第二次调用printX()时传递的参数为(2,3) 此时输出结果为2,然后递归调用printX(3)

第三次调用printX()时传递的参数为(3,) 此时输出结果为3,然后调用printX()  // 这就是声名不带参数的printX()的原因


2. Variadic Templates的特性调用

其实也不算Variadic Templates的特性调用,应该说所有的函数都具有这个特性

#include <iostream>
#include "string" using namespace std; void printX()
{
cout<<"C"<<endl;
} template <typename... Types>
void printX(const Types&... args)
{
cout<<"B"<<endl;
} template <typename T, typename... Types>
void printX(const T& firstArg, const Types&... args)
{
cout<<"A"<<endl;
} int main()
{
printX();
printX(,,,,);
printX();
return ;
}

输出结果

总结: 编译器就喜欢调用有特点的函数(较特化的函数)...


3.举几个Variadic Templates功能的例子


a.   Variadic Templates 实现类似于 printf()的 函数

#include <iostream>

using namespace std;

void printfA(const char *s)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
throw std::runtime_error("invalid format string: missing arguments");
std::cout << *s++ << std:: endl;;
}
}
template<typename T, typename... Args>
void printfA(const char* s, T value, Args... args)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
{
std::cout << value << std::endl;
printfA(++s, args...); // call even when *s == 0 to detect extra arguments
return;
}
std::cout << *s++ << std::endl;
}
throw std::logic_error("extra arguments provided to printf");
}
//~~~~~~~~~~~~~~~ int main()
{
int * pi = new int;
printfA("%d%s%p%f\n",
,
"abc",
pi,
3.1415926
);
return ;
}

输出结果

第一次调用  printfA(%d%s%p%f\n, 10, args...)   输出10

第二次调用  printfA(%s%p%f\n, "abc", args...)   输出abc

第三次调用  printfA(%p%f\n, "pi", args...)      输出[地址]

第四次调用  printfA(%f\n, "3.1415926", )      输出3.1415926

...


b.Variadic Templates 递归创建,递归继承

#include <iostream>

using namespace std;

template<typename Head, typename... Tail>
class tuple<Head,Tail...>:private tuple<Tail...>
{
typedef tuple<Tail...> inherited;
protected:
Head m_head;
public:
tuple() {}
tuple(Head v,Tail... vtail):m_head(v),inherited(vtail...){}//inheriter(vtail...)调用父类的构造函数
auto head()->decltype(m_head){return m_head;}// Head head() { return m_head;}
inherited& tail() {return * this;} }; int main()
{
tuple<int, float, string> t{, 6.3, "nico"};
cout<< sizeof(t) <<endl;
cout<< t.head() <<endl;
cout<< t.tail().head()<<endl;
cout<< t.tail().tail().head() <<endl; return ;
}

输出结果

使用递归继承的方式会将这些变量的储存地址连接起来


c.sizeof...(args)的使用

#include <iostream>

using namespace std;

template <int IDX, int MAX, typename... Args>
struct PRINT_TUPLE {
static void print (ostream& os, const tuple<Args...>& t) {
os << get<IDX>(t) << (IDX+==MAX ? "" : ",");
PRINT_TUPLE<IDX+, MAX, Args...>::print(os,t);
}
};
// partial specialization to end the recursion
template <int MAX, typename... Args>
struct PRINT_TUPLE<MAX, MAX, Args...> {
static void print (std::ostream& os, const tuple<Args...>& t) {
}
};
// output operator for tuples
template <typename... Args>
ostream& operator<< (ostream& os,
const tuple<Args...>& t)
{
os << "[";
PRINT_TUPLE<, sizeof...(Args), Args...>::print(os,t); //sizeof...(args) 会获取参数个数
return os << "]";
} int main()
{
cout<<make_tuple(1.5,"abc",,)<<endl;
return ;
}

输出结果


d.递归复合

#include <iostream>

using namespace std;

template<typename... Values> class tup;
template<> class tup<> { };
template<typename Head, typename... Tail>
class tup<Head, Tail...>
{
typedef tup<Tail...> composited;
protected:
composited m_tail;
Head m_head;
public:
tup() { }
tup(Head v, Tail... vtail)
: m_tail(vtail...), m_head(v) { }
Head head() { return m_head; }
composited& tail() { return m_tail; }
}; int main()
{
tup<int, float, string> t1(, 6.3, "nico");
cout << sizeof(t1) << endl; //
cout << t1.head() << endl; //
cout << t1.tail().head() << endl; //6.3
cout << t1.tail().tail().head() << endl; //nico
return ;
}

输出结果

以上是Variadic Templates几个简单又实用的例子

如有错误请指正

参照<<侯捷 C++新标准 C++11>>

C++11_ Variadic Templates的更多相关文章

  1. C++11 : variadic templates(可变参数模板)

      Introduction: Before the possibilities of the new C++ language standard, C++11, the use of templat ...

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

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

  3. C++2.0新特性(一)——<特性认知、__cplusplus宏开启、Variadic Templates 、左右值区分>

    一.新特性介绍 2.0新特性包含了C++11和C++14的部分 1.2 启用测试c++11功能 C++ 标准特定版本的支持,/Zc:__cplusplus 编译器选项启用 __cplusplus 预处 ...

  4. variadic templates & pass by const reference & member operator [] in const map & gcc sucks

    /// bugs code with comments #include <iostream> #include <memory> #include <unordered ...

  5. C++11_ tuple

    版权声明:本文为博主原创文章,未经博主允许不得转载. tuple 是一个可以装载任何变量的容器,C++11的Variadic Templates给tuple的实现带来了极大方便. tuple的实现基于 ...

  6. C++ Templates (Part I 基本概念 The Basics)

    C++ 模板 (C++ Templates) 目录 C++ 模板 (C++ Templates) 第一部分 基本概念 (The Basics) 第一部分章节目录 参考资料 第一部分 基本概念 (The ...

  7. C/C++ 记录时间

    http://stackoverflow.com/questions/2808398/easily-measure-elapsed-time https://github.com/picanumber ...

  8. (转)C++0x语言新特性一览

    转自:http://blog.csdn.net/zwvista/article/details/2429781 原文请见http://en.wikipedia.org/wiki/C%2B%2B0x. ...

  9. 词频统计_输入到文件_update

    /* 输入文件见337.in.txt 输出文件见338.out.txt */ #include <iostream> #include <cctype> #include &l ...

随机推荐

  1. handle 和module

    <httpHandlers> <add verb="*" path="*" type="ClassLibrary831.TestHa ...

  2. RenderScript多输入参数

    https://stackoverflow.com/questions/20783830/how-to-use-renderscript-with-multiple-input-allocations ...

  3. 照着官网来安装openstack pike之glance安装

    镜像服务image service(glance)的安装还是在控制节点上进行: 1.前提条件,数据库为glance创建库和账户密码来连接数据库 # mysql -u root -p MariaDB [ ...

  4. 20145301实验五 Java网络编程及安全

    北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.05.06 18:30-21:30 实验名称:实验五 Java网络编程 实验内容 ...

  5. Error: Flash Download failed - "Cortex-M0"

    今天在调试程序时.DEMO板下载几次后就提示Flash下载失败:                         Keil v4里面的设置都没有动过.不可能被修改.此时.使用新唐的ICP Progra ...

  6. Oracle查询一个表的数据插入到另一个表

    1. 新增一个表,通过另一个表的结构和数据 create table XTHAME.tab1 as select * from DSKNOW.COMBDVERSION 2. 如果表存在: insert ...

  7. Hive压缩格式

    TextFile Hive数据表的默认格式,存储方式:行存储. 可使用Gzip,Bzip2等压缩算法压缩,压缩后的文件不支持split 但在反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,因此 ...

  8. 【前端】vue.js实现按钮的动态绑定

    vue.js实现按钮的动态绑定 实现效果: 实现代码以及注释: <!DOCTYPE html> <html> <head> <title>按钮绑定< ...

  9. 快速升级openwrt的linux内核版本

    一.分析 要升级openwrt的linux内核版本,关键是要制作内核配置文件 二.内核配置文件制作方法 2.1当前openwrt对应的某个开发板有对应的内核配置文件,比如此时的openwrt的linu ...

  10. openwrt如何查看当前使用的硬件平台

    答:输入cat /tmp/sysinfo/board_name即可获取