关于ofstream的警告,但不是ostream的警告。有什么不同?

时间:2011-12-19 16:24:58

标签: c++ compiler-warnings

这并不重要。但我很好奇这个警告何时出现。我真正的问题是为什么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,那么警告就会消失。知道为什么吗?

2 个答案:

答案 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&

  1. static_cast<ostream&>(os) << t.yint -> Test

  2. os << static_cast<Test>(t.y)

    如果您直接使用ostream&,则int - 解释需要转换,因此是首选。