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 ...
随机推荐
- netty10---分包粘包
客户端:根据 长度+数据 方式发送 package com.server; import java.net.Socket; import java.nio.ByteBuffer; public cla ...
- GATK的硬过滤
https://software.broadinstitute.org/gatk/documentation/article.php?id=2806
- Quick Launcher FAQ
Q: Which category can be previewed and selected in Finder? A: All the categories can be selected in ...
- ubuntu 18.04在更新软件库时出现E: Release file for http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease is not valid yet...
1.完整的错误信息如下: E: Release file for http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease i ...
- static变量、static方法之间的异同
private SchemeBean getEmptyScheme() { SchemeBean scheme = new SchemeBean(); scheme ...
- sublime的一些插件
新安装的sublime缺少一些插件… 1.文件路径没有提示 ctrl+shift+p → install → autofilename 2..html后缀的文件中,使用快捷键!不能自动出现内容 ctr ...
- 实现Promise的first等各种变体
本篇文章主要是想通过ES6中Promise提供的几个方法,来实现诸如first.last.none.any等各种变体方法! 在标准的ES6规范中,提供了Promise.all和Promise.race ...
- kotlin for android----------MVP模式实现登录
学习了Kotlin,随便来个小案例,以MVP+Kotlin 来实现登录的一个小案例,希望对大家有所帮助,效果图: MVP: Model Model 是用户界面需要显示数据的抽象,也可以理解为从业务数据 ...
- Calendar时间获取天,周,月,季度,年度时间段
Date类 Date类的大多数构造函数和方法都已经抛弃,只留下和毫秒有关的操作,目前常用的构造函数 常用方法 设置毫秒数 读取毫秒数 toString()打印结果 //创建日期对象,把当前的毫秒值转成 ...
- 重新学习MySQL数据库8:MySQL的事务隔离级别实战
重新学习Mysql数据库8:MySQL的事务隔离级别实战 在Mysql中,事务主要有四种隔离级别,今天我们主要是通过示例来比较下,四种隔离级别实际在应用中,会出现什么样的对应现象. Read unco ...