如何打印任意编号或随机访问的容器



假设我有N个不同类型的随机访问容器(例如std::vectorstd::array(,并且所有容器都具有相同的长度。我想写一个函数,以列顺序的方式打印它们,即:

#include <vector>
#include <iostream>
#include <array>
#include <complex>
constexpr int nr=100;
void print(const std::vector<double>& d1, const std::array<std::complex<double>,nr>& b1, const std::vector<int>& b2, const std::array<double,nr>& d2)
{
for(int i=0; i<nr; ++i)
std::cout<<b1[i]<<" "<<d1[i]<<" "<<b2[i]<<" "<<d2[i]<<"n";
}

现在假设所有的容器都包含标准的数字类型,我可以编写一个可变模板函数,如下所示:

template<typename... T>
void vprint(T... cs)
{
constexpr int nc=sizeof...(T);
std::vector<std::vector<std::complex<long double>>> v(nr, std::vector<std::complex<long double>>(nc));
//then fill v recursively with all the cs and print it
}

其中我使用了std::complex<long double>,因为它将包含任何可能的数字。然而,这个解决方案并不令人满意,因为我正在分配额外的内存,我正在转换一些破坏输出(可能还有精度(的整数,最后,如果任何容器包含一个无法正常转换为数字类型的可打印类型,则该解决方案不起作用。有没有关于如何编写更通用的解决方案的想法?

您不需要创建任何临时性。以下是一个需要至少有一个容器的实现,但您可以通过添加一个空重载来删除该要求:

// Handles empty parameters by doing nothing
void vprint() {}
// Handle non-empty parameters
template<typename T, typename... Ts>
void vprint(const T& front, const Ts&... cs) {
for (int i = 0; i < front.size(); ++i) {
std::cout << front[i];
((std::cout << ' ' << cs[i]), ...);
std::cout << 'n';
}
}

这使得在手动打印第一个元素之后,使用C++17折叠表达式来打印每个容器的第i个元素。明确地处理第一行也可以确保我们不会在没有分支的每行的末尾(或开头(打印额外的空间。

如果你不能访问C++17,它仍然可以实现,但它会比这更丑陋。

根据Louis的评论,为了安全起见,您还可以在for循环之前添加一个assert,以确保所有容器中至少有front.size()元素:

assert(((cs.size() >= front.size()) && ...));

>=更改为==以实现严格相等。

用法:

int main() {
std::array<int, 4> a{1,2,3,4};
std::vector<int> b{5,6,7,8};
vprint(a, b);
}

打印

1 5
2 6
3 7
4 8

https://godbolt.org/z/z6s34TaT9

最新更新