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的更多相关文章

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

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

  2. 【正则表达式1】C++11正则表达式

    https://www.cnblogs.com/pukaifei/p/5546968.html [正则表达式1]C++11正则表达式   头文件 #include <regex> rege ...

  3. 【读书笔记】2016.11.19 北航 《GDG 谷歌开发者大会》整理

    2016.11.19 周六,我们在 北航参加了<GDG 谷歌开发者大会>,在web专场,聆听了谷歌公司的与会专家的技术分享. 中午免费的午餐,下午精美的下午茶,还有精湛的技术,都是我们队谷 ...

  4. 【编程篇】C++11系列之——临时对象分析

    /*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: /**********************************************/ class CStuden ...

  5. 【机器学习实战】第11章 使用 Apriori 算法进行关联分析

    第 11 章 使用 Apriori 算法进行关联分析 关联分析 关联分析是一种在大规模数据集中寻找有趣关系的任务. 这些关系可以有两种形式: 频繁项集(frequent item sets): 经常出 ...

  6. 【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第11章       STM32H7移植SEGGER的硬 ...

  7. 【C/C++】C++11 Lambda

    Lambda C++11 中 lambda 是一个匿名函数对象 最简形式 []{ cout << "lambda" << endl; }(); // pri ...

  8. 【转帖】iPhone 11 Pro Max皇帝版物料成本不足3500元 卖一赚二

    iPhone 11 Pro Max皇帝版物料成本不足3500元 卖一赚二 https://www.cnbeta.com/articles/tech/894449.htm 供应链的掌控力很重要 苹果今年 ...

  9. 【python基础】第11回 数据类型内置方法 02

    本章内容概要 列表内置方法 字典内置方法 元组内置方法 集合内置方法 可变类型与不可变类型 本章内容详细 1.列表内置方法 list 列表在调用内置方法之后不会产生新的值 1.1 统计列表中的数据值的 ...

随机推荐

  1. 网络-01-端口号-linux端口详解大全

    0 | 无效端口,通常用于分析操作系统1 | 传输控制协议端口服务多路开关选择器2 | 管理实用程序3 | 压缩进程5 | 远程作业登录7 | 回显9 | 丢弃11 | 在线用户13 | 时间17 | ...

  2. [转载]Oracle日期周详解IW

    1 ORACLE中周相关知识描述 1.1           日期格式化函数 TO_CHAR(X [,FORMAT]):将X按FORMAT格式转换成字符串.X是一个日期,FORMAT是一个规定了X采用 ...

  3. RHCSA

     系统管理 redhat 7 破解修改root密码 修改系统主机名 修改系统地址掩码网关 创建系统默认软件仓库 安装系统内核升级 绑定到外部验证服务LDAP.配置 autofs 用户组管理 创建用户组 ...

  4. Oracle rac 监听状态异常远程连接问题解决(TNS-12541 TNS-12560 TNS-00511 Linux Error:111 ORA-12502)

    问题1现象 数据导出脚本执行失败,报错如下 ORA-12537 到服务器上查看,报错: [oracle@test ~]$ lsnrctl status LSNRCTL - Production on ...

  5. Java实训作业1

    1.编写程序:声明一个整型变量a,并赋初值5,在程序中判断a是奇数还是偶数,然后输出判断的结果 2.编写程序:从键盘输入圆的半径,计算圆的面积并输出. 3.编写程序:实现一个数字加密器.运行时输入加密 ...

  6. Android ANR(应用无响应)解决分析【转】

    本文转载自:https://blog.csdn.net/u014630142/article/details/81709459 来自: http://blog.csdn.net/tjy1985/art ...

  7. ng/cli uses yarn as the package manager

    Switch to working directory Excuting the following command ng config cli.packageManager yarn

  8. memcached源码分析-----slab内存分配器

    温馨提示:本文用到了一些可以在启动memcached设置的全局变量.关于这些全局变量的含义可以参考<memcached启动参数详解>.对于这些全局变量,处理方式就像<如何阅读memc ...

  9. 剑指offer 06:旋转数组的最小数字

    题目描述把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转 ...

  10. Linux下“/”和“~”的区别

    在linux中,”/“代表根目录,”~“是代表目录.Linux存储是以挂载的方式,相当于是树状的,源头就是”/“,也就是根目录. 而每个用户都有”家“目录,也就是用户的个人目录,比如root用户的”家 ...