使用元组并尝试使用ostream将其值打印到控制台时,您不能直接使用循环来执行此操作,因为您只能从std :: get访问元组的元素,这需要编译时间常量为它的模板参数。所以我们必须使用一些模板魔法和递归来为我们做这件事;很公平。我有下面的工作代码,只要所有类型都是基本类型,它就会通过ostream打印一个元组:
#include <utility>
#include <iostream>
#include <tuple>
template<std::size_t> struct int_ {};
template<class Tuple, size_t Pos>
std::ostream& print_tuple( std::ostream& out, const Tuple& t, int_<Pos> ) {
out << std::get<std::tuple_size<Tuple>::value - Pos>( t ) << ' ';
return print_tuple( out, t, int_<Pos - 1>() );
}
template<class Tuple>
std::ostream& print_tuple( std::ostream& out, const Tuple& t, int_<1> ) {
return out << std::get<std::tuple_size<Tuple>::value - 1>( t );
}
template<class... Args>
std::ostream& operator<<( std::ostream& out, const std::tuple<Args...>& t ) {
return print_tuple( out, t, int_<sizeof...(Args)>() );
}
int main() {
std::tuple<int, double, std::string> sample = std::make_tuple( 3, 1.723, "Hi!" );
std::cout << sample << '\n';
std::cout << "\nPress any key and enter to quit.\n";
std::cin.get();
return 0;
}
Output
3 1.723 Hi!
Press any key to quit.
这看起来很简单;但是等一下:如果其中一个元组元素不是基本类型怎么办?如果其中一个元素恰好是一个容器,例如矢量,列表,集合或映射,该怎么办?上面的代码分解并失败。让我们使用上面相同的代码和另一个元组的测试样本:
int main() {
// This next line is perfectly fine and compiles without problems
std::tuple<int, double, std::vector<int>> sample2 =
( 1, 2.0, std::vector<int>{ 3,4,5 } );
// Let's use our overloaded operator from before:
std::cout << sample2 << '\n';
// Oh no; the code doesn't even compile any more!
std::cout << "\nPress any key and enter to quit.\n";
std::cin.get();
return 0;
}
从上面的示例中可以看出,元组的重载运算符适用于所有基本类型的<Args...>
;但是,只要其中一个是容器或其他自定义类型,代码就会中断。
如何解决这个问题?我不一定要找一个适合所有人的案例。
我的元组中需要的特定情况是std::vector<int>
,如上所示。如果有人可以告诉我如何让元组重载operator<<()
使用std::vector<int>
,我确信只要std::vector<T>
我可以将其推广到任何<T>
。是一种基本类型。