C++11_ Variadic Templates
版权声明:本文为博主原创文章,未经博主允许不得转载。
这次主要介绍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的更多相关文章
- C++11 : variadic templates(可变参数模板)
Introduction: Before the possibilities of the new C++ language standard, C++11, the use of templat ...
- 【C/C++】C++11 Variadic Templates
Variadic Templates 1.function template:利用“参数个数逐一递减”的特性,实现递归函数调用 template <typename T, typename... ...
- C++2.0新特性(一)——<特性认知、__cplusplus宏开启、Variadic Templates 、左右值区分>
一.新特性介绍 2.0新特性包含了C++11和C++14的部分 1.2 启用测试c++11功能 C++ 标准特定版本的支持,/Zc:__cplusplus 编译器选项启用 __cplusplus 预处 ...
- variadic templates & pass by const reference & member operator [] in const map & gcc sucks
/// bugs code with comments #include <iostream> #include <memory> #include <unordered ...
- C++11_ tuple
版权声明:本文为博主原创文章,未经博主允许不得转载. tuple 是一个可以装载任何变量的容器,C++11的Variadic Templates给tuple的实现带来了极大方便. tuple的实现基于 ...
- C++ Templates (Part I 基本概念 The Basics)
C++ 模板 (C++ Templates) 目录 C++ 模板 (C++ Templates) 第一部分 基本概念 (The Basics) 第一部分章节目录 参考资料 第一部分 基本概念 (The ...
- C/C++ 记录时间
http://stackoverflow.com/questions/2808398/easily-measure-elapsed-time https://github.com/picanumber ...
- (转)C++0x语言新特性一览
转自:http://blog.csdn.net/zwvista/article/details/2429781 原文请见http://en.wikipedia.org/wiki/C%2B%2B0x. ...
- 词频统计_输入到文件_update
/* 输入文件见337.in.txt 输出文件见338.out.txt */ #include <iostream> #include <cctype> #include &l ...
随机推荐
- ABP官方文档翻译 1.1 介绍
介绍 介绍 快速示例 其他 启动模板 如何使用 介绍 我们通常会根据不同的需求来创建不同的应用程序.但是对于一些通用相似的结构总是一遍又一遍的实现,至少在某种程度上是这样的.常见的通用模块如授权.验证 ...
- 验证url格式
//验证url var url=$("#address").val(); var regUrl = /^http[s]{0,1}:\/\/.+$/ ; if(url.match(r ...
- 20145310 《Java程序设计》第7周学习总结
20145310 <Java程序设计>第7周学习总结 教材学习内容总结 本周主要进行第十二章和第十三章的学习. Lambda定义:一个不用被绑定到一个标识符上,并且可能被调用的函数. 在只 ...
- 20145240《网络对抗》逆向及Bof基础实践
逆向及Bof基础实践 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包 ...
- [BZOJ2109]Plane 航空管制
Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的 ...
- POJ_1159 Palindrome (线性动态规划+滚动数组)
题意是说,给定一个字符串,问至少还需要插入多少个字符才能使得该字符串成为回文字符串. 这道题一开始做的时候用了一个简单的动态规划,开了一个5000*5000的数组,用递归形式实现,代码如下: 其中d[ ...
- 使用Spring注解注入属性
本文介绍了使用Spring注解注入属性的方法.使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Pos ...
- cp 复制 mv剪切
cp cp -p test.rb /home/test 将test.rb copy到test目录,并且保留原文件的属性cp -r Dir/ /home/test 将Dir目录copy到te ...
- ImportError: No module named argparse
如果有root权限,可以运行: easy_install argparse 如果没有root权限,As a simple solution copy argparse.py from https:// ...
- springMVC注解的入门案例
1.web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&qu ...