【C/C++】C++11 Variadic Templates
Variadic Templates
1、function template:利用“参数个数逐一递减”的特性,实现递归函数调用
template <typename T, typename... Types>
void func(const T& firstArg, const Types&... args) {
处理 firstArg
func(args...);
}
例一、实现类似 python 3 的 print()
void print() { cout << endl; } // 边界条件,当args为0个时调用
template <typename T, typename... Types>
void print(const T& firstArg, const Types&... args) {
cout << firstArg << ' ';
print(args...);
}
int main() {
print(7.5, "hello", bitset<>(), ); // print "7.5 hello 0000000101111001 42"
return ;
}
如果同时存在函数
template <typename... Types>
void print(const Types&... args) {
...
}
void print(const T& firstArg, const Types&... args) 与 void print(const Types&... args) 可以共存,可以编译通过。
但前者比较特化,后者比较泛化,共存时永远不会调用后者。
例二、模拟 C <cstdio> 的 printf(),引自 stackoverflow
void Printf(const char* s) {
while (*s) {
if (*s == '%' && *(++s) != '%')
throw runtime_error("invalid format string: missing arguments.");
cout << *s++;
}
}
template <typename T, typename... Types>
void Printf(const char* s, const T& firstArg, const Types&... args) {
while (*s) {
if (*s == '%' && *(++s) != '%') {
cout << firstArg;
Printf(++s, args...);
return;
}
cout << *s++;
}
}
int main() {
int* pi = new int;
Printf("[%p] %s = %f\n", pi, "This is pi", 3.1415926); // print "[0x21fcc20] This is pi = 3.14159"
return ;
}
2、class template:利用“参数个数逐一递减”导致“参数类型也逐一递减”的特性,实现递归继承或递归复合
例一、对 first 和 last(头尾元素)的特别处理(模板偏特化+递归)
// 使用tuple index和max index打印元素
template <int IDX, int MAX, typename... Args>
struct print_tuple {
static void print(ostream& os, const tuple<Args...>& args) {
os << get<IDX>(args) << (IDX + == MAX ? "" : ", ");
print_tuple<IDX + , MAX, Args...>::print(os, args);
}
}; // 递归结束的偏特化
template <int MAX, typename... Args>
struct print_tuple<MAX, MAX, Args...> {
static void print(ostream&, const tuple<Args...>&) {}
}; // output operator for tuple
template <typename... Args>
ostream& operator<<(ostream& os, const tuple<Args...>& args) {
os << '[';
// 需要知道tuple的元素index,用sizeof...(Args)获得元素个数
print_tuple<, sizeof...(Args), Args...>::print(os, args);
return os << ']';
} int main() {
cout << make_tuple(7.5, string("hello"), bitset<>(), ); // print "[7.5, hello, 0000000101111001, 42]"
return ;
}
例二、C++STL 中 tuple 的实现(类的递归继承)
template <typename... Values> class tuple;
template <> class tuple<> { }; template <typename Head, typename... Tail>
class tuple<Head, Tail...> : private tuple <Tail...> {
typedef tuple<Tail...> inherited;
public:
tuple() { }
tuple(Head v, Tail... vtail) : m_head(v), inherited(vtail...) { } // 调用base ctor
...
protected:
Head m_head;
};

例三、模拟 tuple(类的递归复合)
template <typename... Values> class tup;
template <> class tup<> { }; template <typename Head, typename... Tail>
class tup<Head, Tail...> {
typedef tup<Tail...> composited;
public:
tup() { }
tup(Head v, Tail... vtail) : m_head(v), m_tail(vtail...) { } // 递归复合
...
protected:
Head m_head;
composited m_tail;
};
只是这种实现 tuple 的方式内存消耗较大
【C/C++】C++11 Variadic Templates的更多相关文章
- C++11 : variadic templates(可变参数模板)
Introduction: Before the possibilities of the new C++ language standard, C++11, the use of templat ...
- 【正则表达式1】C++11正则表达式
https://www.cnblogs.com/pukaifei/p/5546968.html [正则表达式1]C++11正则表达式 头文件 #include <regex> rege ...
- 【读书笔记】2016.11.19 北航 《GDG 谷歌开发者大会》整理
2016.11.19 周六,我们在 北航参加了<GDG 谷歌开发者大会>,在web专场,聆听了谷歌公司的与会专家的技术分享. 中午免费的午餐,下午精美的下午茶,还有精湛的技术,都是我们队谷 ...
- 【编程篇】C++11系列之——临时对象分析
/*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: /**********************************************/ class CStuden ...
- 【机器学习实战】第11章 使用 Apriori 算法进行关联分析
第 11 章 使用 Apriori 算法进行关联分析 关联分析 关联分析是一种在大规模数据集中寻找有趣关系的任务. 这些关系可以有两种形式: 频繁项集(frequent item sets): 经常出 ...
- 【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第11章 STM32H7移植SEGGER的硬 ...
- 【C/C++】C++11 Lambda
Lambda C++11 中 lambda 是一个匿名函数对象 最简形式 []{ cout << "lambda" << endl; }(); // pri ...
- 【转帖】iPhone 11 Pro Max皇帝版物料成本不足3500元 卖一赚二
iPhone 11 Pro Max皇帝版物料成本不足3500元 卖一赚二 https://www.cnbeta.com/articles/tech/894449.htm 供应链的掌控力很重要 苹果今年 ...
- 【python基础】第11回 数据类型内置方法 02
本章内容概要 列表内置方法 字典内置方法 元组内置方法 集合内置方法 可变类型与不可变类型 本章内容详细 1.列表内置方法 list 列表在调用内置方法之后不会产生新的值 1.1 统计列表中的数据值的 ...
随机推荐
- Linux格式化、挂载及卸载数据盘
注意: 磁盘分区和格式化是高风险行为,请慎重操作.本文档描述如何处理一个新买的数据盘,如果您的数据盘上有数据,请务必对数据进行备份以避免可能的数据丢失. 服务器仅支持对 数据盘 进行分区,而不支持对 ...
- linux下列出所有连接到你的Server的IP地址
linux下列出所有连接到你的Server的IP地址 最近要做一个检查所有连接到主机的IP的脚本,google到一篇老外写的文章 <List all IP addresses connected ...
- caffe常用
1. 关闭模型froward信息 os.environ[' #注意要在improt caffe之前 2. 学习率 step: 配合stepsize,迭代次数达到stepsize的整数倍改变一次, ba ...
- 自动获取客户端的ip地址
document.writeln('<script src=\"http://pv.sohu.com/cityjson?ie=utf-8\"></script&g ...
- java RSA实现私钥签名、公钥验签、私钥加密数据、公钥解密数据
通过OpenSSL生成公私钥文件(如果没有OpenSSL工具建议下载Cmder工具自带OpenSSL指令) 1.生成RSA密钥的方法 genrsa -out private-rsa.key 2048 ...
- 随手记一 2018/04/23 Ajax基础了解
1.什么是ajax? 主要目的是用来实现客户端和服务器之间的异步通信,实现页面的局部刷新 2.同步和异步! 同步:当多个线程同时向一个数据发送请求时,必须是A先执行完毕才可以给B,会出现阻塞的情况,但 ...
- windows版jmeter的body data如何用\n作为“换行”
前段时间用jmeter进行某个web接口性能测试的时候遇到一个问题,body data中的换行的内容发送后,通过抓包发现总是发送"0D0A"即"\r\n"(wi ...
- golang设置title并获取窗口句柄
package main import ( "fmt" "syscall" "github.com/lxn/win") func main( ...
- 移动端开发注意事项——meta、rem以及弹性盒
移动端开发注意事项——meta.rem以及弹性盒 随着人们对移动端的依赖程度的增强,前端开发对移动端的需求也越来越强烈.那么,在移动端开发中,有哪些事项是需要注意的呢? meta标签 在常规的pc端开 ...
- idea使用的小技巧总结
1.需要一个快捷清爽的控制台? 下面这段配置是你需要的,在workspace.xml里面添加 <component name="RunDashboard"> <o ...