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 ...
随机推荐
- linux pip 查看版本提示
After upgrading pip (or pip3, in this case) if the following occurs: $ ~ pip3 -V Traceback (most rec ...
- Java-Minor GC、Major GC、Full GC
Minor GC: 回收年轻代(Young)空间,包括Eden区.Survivor区. JVM无法为一个新对象分配空间时,比如eden区满了,就会触发Minor GC. Major GC: 清理永久代 ...
- 20145309《Java程序设计》第七周学习总结
教材学习内容总结 第13章 时间与日期 13.1 认识时间与日期 13.1.1 时间的度量 格林威治时间(GMT) 世界时(UT) 国际原子时(TAI) 世界协调时间(UTC) Unix时间:Unix ...
- 20145313张雪纯 《Java程序设计》第9周学习总结
20145313张雪纯 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行操作,开发人员无需接 ...
- bat批处理以当前时间创建文本文件
:: 表示注释 :: @表示不显示当前命令,只在后台执行 :: @echo off 表示以后执行的命令都不显示 :: set d=%,% 表示设置变量d为当前年月日,默认表示为例如:// :: set ...
- Rank - 第二类斯特灵数
2017-08-10 20:32:37 writer:pprp 题意如下: Recently in Teddy's hometown there is a competition named &quo ...
- HDU 1827 Summer Holiday
http://acm.hdu.edu.cn/showproblem.php?pid=1827 题意: 听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家 ...
- javaScript实现点击按钮直接打印
很多网站都有此功能,当浏览到底部时都会有一个打印按钮,点击打印按钮就可以完成打印功能,功能非常不错,人性化,代码非常的简单. 一.只要调用window.print()函数就可以实现打印当前页面 < ...
- LeetCode第[88]题(Java):Merge Sorted Array(合并已排序数组)
题目:合并已排序数组 难度:Easy 题目内容: Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as ...
- 【转】Scikit-learn技巧(拓展)总结
最近看了<Python数据挖掘入门与实战>,网上有说翻译地不好的,但是说实话,我觉得这本书还是相当不错的.作者Robert Layton是sklearn的开发者之一,书中介绍了很多skle ...