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

这次主要介绍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. 使用.NET Core和Vue搭建WebSocket聊天室

    博客地址是:https://qinyuanpei.github.io.  WebSocket是HTML5标准中的一部分,从Socket这个字眼我们就可以知道,这是一种网络通信协议.WebSocket是 ...

  2. C++ 单链表的实现

    #ifndef LINKEDLIST_H #define LINKEDLIST_H #define MAXLEN 256 template <class T> struct LinkedL ...

  3. java压缩多个文件

    首先创建一个工具类,定义好接口,这里的参数1:fileList:多个文件的path+name2: zipFileName:压缩后的文件名 下面是代码,注释已经很详细了 public class ZIP ...

  4. HBase相关问题

    HBase和Hive的异同之处? 共同点:HBase与Hive都是架构在Hadoop之上,底层存储都是使用HDFS 区别: 1). Hive是建立在Hadoop之上为了减少MapReduce jobs ...

  5. ifconfig设置ip时出现提示 ifconfig: SIOCSIFFLAGS: Address not available

    一.笔者使用ifconfig观察网卡情况如下: root@jello:/# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:00:00:00:00:0 ...

  6. 【转载】解决window.showModalDialog 模态窗口中location 打开新窗口问题

    来源: <http://bibipear.blog.sohu.com/143449988.html> 在我们的项目中,通常会用到showModalDialog 打开一个模态的子窗口,但是在 ...

  7. SaltStack应用grains和jinja模板-第四篇

    目标需求 1.使用jinja模板让apache配置监听本地ip地址 2.了解grains的基本使用方法 说明:实验环境是在前面的第二篇和第三篇基础上完成 实现步骤 使用grains获取ip地址信息 使 ...

  8. Centos7.2 FastDFS_V5.05 集群的安装与配置1

    环境: Centos 7.2/64位  两台服务器 都为tracker 和 storage 10.100.0.1  storage tracker10.100.0.2  storage tracker ...

  9. 总结网站Mysql优化

    Mysql存储引擎 选择合适的存储引擎Innodb  myisam myisam: 写入数据非常快,适合使用场合dedecms/phpcms/discuz/微博系统等写入.读取操作多的系统. inno ...

  10. java 不可不知的数据库知识-----事物

    每一个java开发对数据库都不会陌生,提到数据库,那么就一定要了解的一个知识点------事物,下面就对事物简单记录一下相关知识点. 最初接触事物的时候其实是从JDBC事物开始的,JDBC比较基础,这 ...