向量打印矢量ostream

时间:2012-05-08 15:08:15

标签: c++ vector ostream

请考虑以下代码。我正在尝试将矢量矢量输出到ostream。

#include <iterator>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
    using namespace std;
    copy(v.begin(), v.end(), ostream_iterator<T>(os, "\n"));
    return os;
}

int main() {
    using namespace std;
    vector<string> v1;
    cout << v1;
    vector<vector<string> > v2;
    cout << v2;
    return 0;
}

我输出字符串向量的语句有效。我输出字符串向量向量的那个没有。我正在使用g ++ 4.7.0。我试过w /&amp;没有-std = c ++ 11标志。在C ++ 11模式下,它在半页的错误中给出了这一行。

error: cannot bind 'std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >::ostream_type {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

我认为我不明白这意味着什么。有人可以向我解释一下吗?我或多或少知道rvalue引用是什么,但我不明白为什么std::basic_ostream<char>不会绑定到std::basic_ostream<char>&&。也许我不太了解它。还有更好的方法吗?

提前致谢。

2 个答案:

答案 0 :(得分:8)

你得到的错误有点误导。当我尝试编译你的程序时,我不得不深入挖掘模板呕吐物,我最终得到了我的想法:

error: no match for 'operator<<' in '*((std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >*)this)->std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >::_M_stream << __value'

基本上,当你调用复制算法时,它使用了输出迭代器,它使用了&lt;&lt;来自命名空间std中的operator。在那里,查找表明它试图找到模板向量的重载&lt;&gt;在std命名空间中(因为这就是IT所在的位置)。

所以你需要做的是在namespace std中为vector模板声明你的stream运算符。使用namespace std {}包围您的代码,看看会发生什么......

应该注意的是,你所做的基本上是修改std :: vector&lt;&gt;并添加以前不存在的行为。这样做是非标准的,未定义的,并且很容易妨碍你。您可以考虑其他选择。


我错了,这是一个koenig查找的东西。它不是,问题是名称隐藏类似于类中发生的事情,你声明基础中的某些东西(不是覆盖)的重载。

标准名称空间声明了几个'&lt;&lt;'运营商。这些基本上是名为operator <<的函数。从本质上讲,你拥有的是:

void fun(int);

namespace Test {

  void fun() { fun(3); }

}

int main() {
    Test::fun();
}

请注意,您可以使用全局命名空间中的fun(int)或任何没有任何名为fun的函数的命名空间。您无法在Test命名空间中使用它。

这就是你使用运算符&lt;&lt;声明全局从全局命名空间工作正常,但不在std命名空间内工作。 std命名空间的名称与您尝试提供的重载名称相同,因此std中的所有内容都隐藏了重载。如果您可以使用声明,那么事情会有所不同。

答案 1 :(得分:4)

您需要此实用程序库:


如果你想自己这样做(以便自学),那么你需要定义两个重载:

  • std::vector<T>

    template<typename T>
    std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
       using namespace std;
       copy(v.begin(), v.end(), ostream_iterator<T>(os, "\n"));
       return os;
    }
    
  • std::vector<std::vector<T>>

    template<typename T>
    std::ostream &operator <<(std::ostream &os, const std::vector<std::vector<T>> &v) {
       using namespace std;
    
       //NOTE: for some reason std::copy doesn't work here, so I use manual loop
       //copy(v.begin(), v.end(), ostream_iterator<std::vector<T>>(os, "\n"));
    
       for(size_t i = 0 ; i < v.size(); ++i)
            os << v[i] << "\n";
       return os;
    }
    

如果你有这些重载,那么它们将一起递归地处理这些情况:

std::vector<int>  v;
std::vector<std::vector<int>>  vv;
std::vector<std::vector<std::vector<int>>>  vvv;
std::vector<std::vector<std::vector<std::vector<int>>>>  vvvv;

std::cout << v << std::endl; //ok
std::cout << vv << std::endl; //ok
std::cout << vvv << std::endl; //ok
std::cout << vvvv << std::endl; //ok