C ++模板使用模板递归打印向量的向量

C++ template recursively print a vector of vector using template

#include <any>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

template<class T>
struct is_vector : std::false_type {};
template<class T>
inline constexpr bool is_vector_v = is_vector<T>::value;

template <typename T>
string VectorToString(const vector<T> &vec)
{
    string res = "[";
    int n = vec.size();
    for (size_t i=0; i<n; i++) {
        if constexpr(is_vector_v<T>) res += VectorToString(vec[i]);
        else res += std::to_string(vec[i]);
        if (i < n-1) res += ", ";
    }
    res += "]";
    return res;
}

int main( int argc, char** argv ) 
{        
    vector<int> a = {1,2,3};
    cout << VectorToString(a) << "\n";

    vector<vector<int>> b = {{1,2,3}, {4,5,6}, {7,8,9}};
    //cout << VectorToString(b);    

    vector<vector<vector<double>>> c = {{{1,2,3}, {4,5,6}}, {{7,8,9}}};
    //cout << VectorToString(c);    
    return 0;
}

我正在尝试制作适用于任何矢量类型的打印函数,例如 Python。

我希望尽可能使用模板,但不确定如何使用。 struct is_vector 应该怎么做才能做到这一点?

如果模板解决方案不可行,那么我希望看到任何可能的解决方案。

一种选择是混合使用模板和运算符重载,如下所示。特别是,为 std::vector 重载 operator<<。下面给出了一个非常粗糙的例子。它打印 std::vector.

的所有元素
//this will be selected for 1D std::vector
template<typename T> 
std::ostream& operator<<(std::ostream &os, const std::vector<T> &vec)
{
    for(auto it = vec.begin(); it!=vec.end(); ++it)
    {
        os<< (*it)<<" ";
    }
    return os;
}
//for arbitrarily nested std::vector
template<typename T> 
std::ostream& operator<<(std::ostream &os, const std::vector<std::vector<T>> &vec)
{
    
    for(auto it = vec.begin(); it!=vec.end(); ++it)
    {
        os << *it;
    }
    
    return os;
}
int main()
{
    std::vector<int> vec1{1,2,3};
    std::cout<<vec1<<std::endl; //prints 1 2 3 
    
    std::vector<std::vector<int>> vec2 = {{1,2,3}, {4,5,6}, {7,8,9}}; //1 2 3 4 5 6 7 8 9
    std::cout<<vec2<<std::endl;
    
    std::vector<std::vector<std::vector<double>>> vec3{{{1,2,3}, {4,5,6}, {7,8,9}}, {{-1,-2,-3}, {-4,-5,-6}, {-10,-22,36}}, {{129,212,999}, {0,0,1}, {3,5,4}}};
    std::cout<<vec3<<std::endl;
    return 0;
}

以上程序的输出为:

1 2 3
1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 -1 -2 -3 -4 -5 -6 -10 -22 36 129 212 999 0 0 1 3 5 4

Demo.

另一种选择是使用折叠表达式。

What should struct is_vector looks like to do this?

看起来像模板偏特化的样子

template<class T>
struct is_vector : std::false_type {};

template<class T, class Alloc>
struct is_vector<std::vector<T, Alloc>> : std::true_type {};

Demo