【发布时间】:2013-04-02 17:39:24
【问题描述】:
我正在尝试漂亮地打印一个 STL 容器。我想要的是打印用分隔符分隔的容器的元素。 但是我遇到了几个问题。
1. g++ vs VC++
ostream& operator<<(ostream& o, const vector<string>& v) {
copy(v.begin(), v.end(), std::ostream_iterator<string>(o,","));
}
int main()
{
vector<string> s_v;
s_v.push_back("one");
s_v.push_back("two");
cout << s_v;
}
g++(mingw32 上的 gcc 版本 4.4.0)可以编译它并且工作正常。 VC++ (Visual Studio 9) 无法编译此代码。
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::string' (or there is no acceptable conversion)
1> c:\program files (x86)\microsoft visual studio 9.0\vc\include\ostream(653): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)'
1> with
1> [
这是为什么呢?这个代码是非法的吗?还是只是 VC++ beign VC++?
2。未使用的模板变量会中断编译。
如果现在我像这样在 ostream 中添加一个模板(没有使用,只是坐在那里)
template <typename T> // <----- Here
ostream& operator<<(ostream& o, const vector<string>& v) {
copy(v.begin(), v.end(), std::ostream_iterator<string>(o,","));
}
int main()
{
vector<string> s_v;
s_v.push_back("one");
s_v.push_back("two");
cout << s_v;
}
gcc 无法再匹配运算符了。
error: no match for 'operator<<' in 'std::cout << s_v'
and a lot more candidates...
为什么?该模板未使用。重要吗?
编辑:这已解决。我不得不返回 o;
3.使用的模板
template <typename T>
ostream& operator<<(ostream& o, const vector<T>& v) {
copy(v.begin(), v.end(), std::ostream_iterator<T>(o,","));
return o; // Edited
}
int main()
{
vector<string> s_v;
s_v.push_back("one");
s_v.push_back("two");
vector<int> i_v;
i_v.push_back(1);
i_v.push_back(2);
cout << s_v;
cout << i_v;
}
如果我知道使用模板类型。 g++ 可以编译它,但随后以异常终止。
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
VC++ 只是坐着看着 gcc 做这一切。不编译任何一个。
有人可以帮我澄清一下吗?谢谢。
【问题讨论】:
-
在 std 命名空间中定义你的操作符。你会看到区别
-
如果编译器不能推断模板参数的类型,你必须自己提供。所以如果你有
template<typename T> void Foo() { ... },你需要使用Foo<Type>()。显然,当您重载运算符时,您不能这样做。当您确实使用T时,编译器能够推断其类型,这就是它起作用的原因。 -
另外,你在 ideone 上的最后一个例子 runs fine。不过,您可能希望将
return o;添加到您的operator<<。如果您执行cout << s_v << i_v,这很可能会使您的程序崩溃。 -
@PiotrNycz 不要在
std::中定义运算符,除非它涉及您在某处定义的类型。否则,代码是非法的。 -
@Curious 我无法重现该错误。一旦我修复了明显的错误(缺少包含、缺少
std::、缺少返回),它就可以在我的系统(VC++ 11)中使用。
标签: c++ templates operator-overloading