Aar*_*aid 7 c++ compiler-warnings
这并不重要.但我很好奇这个警告何时出现.我真正的问题是为什么ostream和ofstream被区别对待.
struct Test {
int y;
Test(int k) : y(k) {}
};
Run Code Online (Sandbox Code Playgroud)
使用这个简单的结构,编译器可以看到一个int可以转换为Test.
因此,我收到此代码的警告:
std :: ofstream& operator<< (std :: ofstream& os, const Test& t)
{
os << t.y;
return os;
}
Run Code Online (Sandbox Code Playgroud)
当它看到os << t.y它不知道我是否想要推送名为ty的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&)
Run Code Online (Sandbox Code Playgroud)
无论如何,解决这个问题的一种方法是将Test中的构造函数标记为explicit.我可以忍受这一点.但奇怪的是,如果ofstream被替换ostream,那么警告就会消失.知道为什么吗?
你打电话的时候
os << t.y;
Run Code Online (Sandbox Code Playgroud)
你有2个候选人:
ostream& operator << (ostream&, int) //1
Run Code Online (Sandbox Code Playgroud)
和
ofstream& operator << (ofstream&, Test) //2
Run Code Online (Sandbox Code Playgroud)
没有这样的候选人
ofstream& operator << (ofstream&, int) //3
Run Code Online (Sandbox Code Playgroud)
根据重载决策规则,1和2都不适合您的呼叫.因此警告.如果是ostream,1显然是更好的匹配,因为两个参数完全匹配.
最好的解决方案是配合使用std::ostream.为什么需要专门为文件流重载.如果您需要将其流式传输到字符串中该怎么办?重载输出流操作符std::ostream(或甚至是模板化版本std::basic_ostream)并让编译器处理其余的操作.
正如警告告诉您的那样,ofstream两种解释都需要转换:
ofstream& -> ostream&在static_cast<ostream&>(os) << t.y,
int -> Test 在 os << static_cast<Test>(t.y)
如果你ostream&直接使用,那么int-interpretation 不需要转换,因此是首选.