C++ 如何重载三维向量的ostream操作符?

C++ 如何重载三维向量的ostream操作符?,c++,vector,operator-overloading,C++,Vector,Operator Overloading,如何重载三维向量的流提取操作符 vector<vector<vector<int>>> V(5, vector<int>>(3, vector<int>(2))) 向量V(5,向量>(3,向量(2))) 我提出了以下回应。为什么下面的代码不正确 template <typename T> ostream& operator<<(ostream &output, vector<T&g

如何重载三维向量的流提取操作符

vector<vector<vector<int>>> V(5, vector<int>>(3, vector<int>(2)))
向量V(5,向量>(3,向量(2))) 我提出了以下回应。为什么下面的代码不正确

template <typename T>
ostream& operator<<(ostream &output, vector<T> &V) {
    for(int i = 0; i < V.size(); i++)
        for(int j = 0; j < V[i].size(); j++) 
            output << V[i][j] << " ";
    return output;
}
模板

ostream&operator首先,一个一般性的评论:在任何语言中,将三维向量表示为向量向量向量都不是一个好主意。请不要传播此反模式

存储多维向量的正确方法是使它们在一维向量中“展平”。使用行主顺序的二维示例:

这是您的二维向量/数组:

00 01 02
10 11 12
您将按行主顺序将其存储为:

00 01 02 10 11 12
并相应地对元素进行索引。
[i][j]
-th元素位于平面1D数组中的
[i*colno+j]
,其中
colno
是列数。但是,请注意,如果需要“不规则数组”,即最后一个维度包含大小不等的行,则需要更多的思考


其次,您应该使用适当的库来处理这种多维数组/向量。有很多这样的循环,您可以查看,例如,它附带提供了一个重载的
循环
j
的限制条件不正确,您需要
j

你说你的向量有三维,但你的向量只在二维上循环

现在还不清楚您要传递给流操作符的是什么类型,但我假设它类似于
std::vector
,因为您没有修改它,所以应该通过const引用传递它

我想你要找的是这样的东西:

template<typename T>
using Vector = std::vector<std::vector<std::vector<T>>>;

template <typename T>
std::ostream& operator<<(std::ostream& output, const Vector<T>& v) {
  for(size_t i = 0; i < v.size(); i++) {
    for(size_t j = 0; j < v[i].size(); j++) {
      for(size_t k = 0; k < v[i][j].size(); k++)
        output << v[i][j][k] << " ";
      output << "\n";
    }
    output << "\n";
  }
  return output;
}
模板
使用Vector=std::Vector;
样板

std::ostream&operator我花了一点时间才想出一个通用的解决方案,但它是:

#include <iostream>
#include <vector>


template <typename T, typename _ = void>
struct is_vector : std::false_type
{
};

template <typename T>
struct is_vector< T, typename std::enable_if<std::is_same<T,std::vector< typename T::value_type,typename T::allocator_type >>::value
>::type>
: std::true_type
{
};

template<class T>
auto
emit(std::ostream& os, const T& t, size_t indent = 0)
-> std::enable_if_t<!is_vector<T>::value>
{
    os << std::string(indent, ' ') << t;
}

template<class T, class A>
auto
emit(std::ostream& os, const std::vector<T, A>& v, size_t indent = 0)
-> std::enable_if_t<!is_vector<T>::value>
{
    std::cout << std::string(indent, ' ') << "{ ";
    const char* sep = "";
    for (const auto& i : v) {
        os << sep;
        emit(os, i);
        sep = ", ";
    }
    os << " }";
}

template<class T, class A>
auto
emit(std::ostream&os, const std::vector<T, A>& v, size_t indent = 0)
-> std::enable_if_t<is_vector<T>::value, void>
{
    const auto prefix = std::string(indent, ' ');

    std::cout << prefix << "{\n";
    const char* sep = "";
    for (const auto& i : v) {
        os << sep;
        emit(os, i, indent + 2);
        sep = ",\n";
    }
    os << "\n" << prefix << "}";
}

template<class T, class A>
std::ostream& operator<<(std::ostream&os, const std::vector<T, A>& v)
{
    emit(os, v);
    return os;
}


using VI = std::vector<int>;
using VVI = std::vector<VI>;
using VVVI = std::vector<VVI>;

    using namespace std;

int main(int argc, char **argv)
{
    auto vi = VI { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    cout << "\n1 dimension:\n";
    cout << vi << endl;

    auto vvi = VVI {
        {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        {10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
    };
    cout << "\n2 dimensions:\n";
    cout << vvi << endl;

    auto vvvi = VVVI {
        {
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
            {10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
        },
        {
            {20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
            {30, 31, 32, 33, 34, 35, 36, 37, 38, 39 },
        }
    };
    cout << "\n3 dimensions:\n";
    cout << vvvi << endl;
    return 0;
}

缺少return语句是代码的一个问题。缺少对问题的描述是问题的一个问题。什么是
向量
?(大写V)@RichardHodges一个大胆的猜测说它是使用Vector=Vector的
模板;)或者这就是可能的情况。@vsoftco假设是这样,我发布了一个通用矢量打印作为答案。这是一个很好的方法!
#include <iostream>
#include <vector>


template <typename T, typename _ = void>
struct is_vector : std::false_type
{
};

template <typename T>
struct is_vector< T, typename std::enable_if<std::is_same<T,std::vector< typename T::value_type,typename T::allocator_type >>::value
>::type>
: std::true_type
{
};

template<class T>
auto
emit(std::ostream& os, const T& t, size_t indent = 0)
-> std::enable_if_t<!is_vector<T>::value>
{
    os << std::string(indent, ' ') << t;
}

template<class T, class A>
auto
emit(std::ostream& os, const std::vector<T, A>& v, size_t indent = 0)
-> std::enable_if_t<!is_vector<T>::value>
{
    std::cout << std::string(indent, ' ') << "{ ";
    const char* sep = "";
    for (const auto& i : v) {
        os << sep;
        emit(os, i);
        sep = ", ";
    }
    os << " }";
}

template<class T, class A>
auto
emit(std::ostream&os, const std::vector<T, A>& v, size_t indent = 0)
-> std::enable_if_t<is_vector<T>::value, void>
{
    const auto prefix = std::string(indent, ' ');

    std::cout << prefix << "{\n";
    const char* sep = "";
    for (const auto& i : v) {
        os << sep;
        emit(os, i, indent + 2);
        sep = ",\n";
    }
    os << "\n" << prefix << "}";
}

template<class T, class A>
std::ostream& operator<<(std::ostream&os, const std::vector<T, A>& v)
{
    emit(os, v);
    return os;
}


using VI = std::vector<int>;
using VVI = std::vector<VI>;
using VVVI = std::vector<VVI>;

    using namespace std;

int main(int argc, char **argv)
{
    auto vi = VI { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    cout << "\n1 dimension:\n";
    cout << vi << endl;

    auto vvi = VVI {
        {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        {10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
    };
    cout << "\n2 dimensions:\n";
    cout << vvi << endl;

    auto vvvi = VVVI {
        {
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
            {10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
        },
        {
            {20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
            {30, 31, 32, 33, 34, 35, 36, 37, 38, 39 },
        }
    };
    cout << "\n3 dimensions:\n";
    cout << vvvi << endl;
    return 0;
}
1 dimension:
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }

2 dimensions:
{
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
  { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }
}

3 dimensions:
{
  {
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
    { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }
  },
  {
    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
    { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 }
  }
}
Program ended with exit code: 0