如何打印任意数字或随机访问容器?

ape*_*lle 2 c++ variadic variadic-templates

假设我有 N 个不同类型的随机访问容器(std::vector例如std::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";
}
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

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

Fat*_*KIR 7

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

// 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';
    }
}
Run Code Online (Sandbox Code Playgroud)

这利用 C++17折叠表达式在手动打印第一个元素后打印每个容器的第 i 个元素。显式处理第一个还可以确保我们不会在没有分支的每行末尾(或开头)打印​​额外的空格。

如果你无法访问C++17,它仍然可以实现,但会比这丑陋得多。

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

assert(((cs.size() >= front.size()) && ...));
Run Code Online (Sandbox Code Playgroud)

>=将to更改==为严格相等。

用法:

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

印刷

1 5
2 6
3 7
4 8
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/z6s34TaT9