转自:https://blog.csdn.net/lanchunhui/article/details/49868077
在设计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;
}