这并不重要。但我很好奇这个警告何时出现。我真正的问题是为什么ostream和ofstream被区别对待。
struct Test {
int y;
Test(int k) : y(k) {}
};
使用这个简单的结构,编译器可以看到int
可以转换为Test
。
因此,我收到此代码的警告:
std :: ofstream& operator<< (std :: ofstream& os, const Test& t)
{
os << t.y;
return os;
}
当它看到os << t.y
时,它不知道我是否想要推送名为t.y的int,或者我是否想先将int转换为Test然后再推送它。这看起来很奇怪,你认为它更喜欢非转换的int重载ofstream& operator<< (ofstream &os, int)
。
g ++(Ubuntu 4.4.3-4ubuntu5)4.4.3:
template_expl.cpp: In function ‘std::ofstream& operator<<(std::ofstream&, const Test&)’:
template_expl.cpp:15: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
/usr/include/c++/4.4/bits/ostream.tcc:105: note: candidate 1: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
template_expl.cpp:13: note: candidate 2: std::ofstream& operator<<(std::ofstream&, const Test&)
无论如何,解决此问题的一种方法是将Test中的构造函数标记为explicit
。我可以忍受这一点。但奇怪的是,如果用ofstream
替换ostream
,那么警告就会消失。知道为什么吗?
答案 0 :(得分:7)
致电时
os << t.y;
你有两个候选人:
ostream& operator << (ostream&, int) //1
和
ofstream& operator << (ofstream&, Test) //2
没有这样的候选人
ofstream& operator << (ofstream&, int) //3
根据重载决策规则,1和2都不适合您的呼叫。因此警告。在ostream
的情况下,1显然是更好的匹配,因为两个参数完全匹配。
最佳解决方案是使用std::ostream
。为什么需要专门为文件流重载。如果您需要将其流式传输到字符串中该怎么办?重载std::ostream
的输出流运算符(甚至是std::basic_ostream
的模板化版本)并让编译器处理其余的。
答案 1 :(得分:5)
警告告诉您,ofstream
这两种解释都需要转换:
ofstream& -> ostream&
, 中 static_cast<ostream&>(os) << t.y
在int -> Test
os << static_cast<Test>(t.y)
醇>
如果您直接使用ostream&
,则int
- 解释需要否转换,因此是首选。