C++11::遍历tuple中的元素
来源:互联网 发布:啪啪软件下载 编辑:程序博客网 时间:2024/06/01 08:50
结尾有彩蛋:-D。
阅读本文之前你需要懂至少一下知识:
tuple
tuple,元组类型。头文件<tuple>,tuple是一个固定大小的不同类型(异质,heterogeneous)值的集合(这一点是tuple与其他常规STL容器的最大不同,即它可以同时存放不同类型的数据),是泛化的std::pair(也即std::pair是tuple的一个特例,长度受限为2)。这里插一句嘴,tuple元组类型是python原生的基本数据类型(C++新标准也引入了lambda函数对象,似乎语言之间有一种互相学习走向趋同的趋势),关于python中的元组类型,可参阅我的Python 基础——list的成员方法。
decltype
C++11引入的新的关键字,用以根据变量推导变量的数据类型
非类型模板参数
关于非类型模板参数详细的内容请参见之前的模板系列,<C++基础——非类型模板参数>
在设计tuple的遍历程序之前,我们不妨先进行std::pair的打印工作:
// #include <utility>cout << make_pair("InsideZhang", 23) << end; // ("InsideZhang", 23)
为了实现上述的功能,我们需要重载<<
运算符。
template<typename T1, typename T2>std::ostream& pair_print(std::ostream& os, const pair<T1, T2>& p){ return os << "(" << p.first << ", " << p.second << ")";}
当我们试图仿照上例的形式实现对tuple的遍历输出时:
template<typename... Args>std::ostream& operator<<(std::ostream& os, const std::tuple<Args...>& t){ os << "(" << std::get<0>(t); for (size_t i = 1; i < sizeof...(Args) << ++i) os << ", " << std::get<i>(t); return os << "]";}int main(int, char**){ cout << make_tuple("InsideZhang", 23, "HeNan") << endl; // 编译出错,局部变量i不可作为非类型模板参数 return 0;}
这时我们便需要单独把每一位的索引拿出来作为非类型模板参数进行递归调用:
template<typename Tuple>void tuple_print(const Tuple& t, size_t N, std::ostream& os){ if (N != 1) tuple_print(t, N-1, os); os << std::get<N-1>(t);}
以上的代码, 也即通过参数传递的方式进行的非类型模板参数的赋值,仍然编译不通过。非类型模板参数必须在编译时即为常量表达式。
template<typename Tuple, size_t N>void tuple_print(const Tuple& t, std::ostream& os){ if (N != 1) tuple_print<Tuple, N-1>(t, os); os << std::get<N-1>(t);}
这样做似乎也编译不通过,具体为什么,一时也想不出来,大家有什么思路和想法不妨提供一下。
以下是一个通行的解决方案:
template<typename Tuple, size_t N>struct tuple_print{ static void print(const Tuple& t, std::ostream& os) { tuple_print<Tuple, N-1>::print(t, os); os << ", " << std::get<N-1>(t); }};// 类模板的特化版本template<typename Tuple>struct tuple_print<Tuple, 1>{ static void print(const Tuple& t, std::ostream& os) { os << "(" << std::get<0>(t); }};// operator<<template<typename... Args>std::ostream& operaotr<<(std::ostream& os, const std::tuple<Args...>& t){ tuple_print<decltype(t), sizeof...(Args)>::print(t, os); return os << ")";}
客户端代码:
auto t1 = std::make_tuple("InsideZhang", 23, "HeNan");auto t2 = std::make_tuple("InsideLi", 23, "AnHui");// tuple_cat() 元组拼接// 调用operator<< 运算符重载std::cout << std::tuple_cat(t1, t2) << std::endl;// (InsideZhang, 23, HeNan, InsideLi, 23, AnHui)
因为tuple类没有重载
operator[]
运算符,很难像其他容器和数据额结构一样进行简洁的索引动作,只能通过一个全局的std::get<size_t>(t)
进行操作。
tuple class最早公开于Boost程序库。在那儿,tuple可以将元素写至output stream,不知道为什么C++标准库不支持这一性质,而是需要我们花费一些精力手动完成这一工作。
#include <iostream>#include <boost\tuple\tuple_io.hpp>int main(int, char**){ std::cout << boost::make_tuple("InsideZhang", 23, "HeNan") << std::endl; return 0;}
References
[1]<Pretty-print std::tuple>
- C++11::遍历tuple中的元素
- Python 遍历set的元素是tuple
- 打印变长tuple中的所有元素值
- 遍历ArrayList中的元素
- 遍历集合中的元素
- 使用<c:forEach>标签遍历List中的map元素
- 巧用enum来获取std::tuple中的元素
- 为tuple中的元素命名,提高程序的可读性
- c:forEach 遍历集合中的元素,判断是否是最后一个元素
- c:forEach 遍历集合中的元素,判断是否是最后一个元素
- c:forEach 遍历集合中的元素,判断是否是最后一个元素
- c:forEach 遍历集合中的元素属性详解,判断是否是最后一个元素,
- js:遍历容器中的元素
- java遍历Map中的元素
- pertl 遍历hash中的元素
- java遍历Map中的元素
- java 遍历HashSet中的元素
- 遍历删除List中的元素
- 1026优先队列
- PostMan——使用方法
- 从Java代码到字节码
- iOS开发之指纹解锁
- nodejs npm gulp bower 几点
- C++11::遍历tuple中的元素
- Cookie的一些小思考
- Python Using EXE
- 第八周 项目3-3
- 不可变服务器和无核化unikernel ( by quqi99 )
- 数据结构实践—— 二叉树算法验证(中序线索化二叉树的算法验证)
- 定时检测Memcached进程是否存在,若不存在自动启动它
- 1042. Shuffling Machine (20)
- 第12周-项目3 - 图遍历算法实现