请考虑以下代码。我正在尝试将矢量矢量输出到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>&&
。也许我不太了解它。还有更好的方法吗?
提前致谢。
答案 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