предупреждение о неоднозначном для ofstream, но не для ostream. Какая разница?
это не важно. Но мне любопытно, когда появится это предупреждение. Мой реальный вопрос заключается в том, почему 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
он не знает, хочу ли я нажать int под названием t.y, или я хочу преобразовать int в тест сначала, а потом толкай. Это кажется довольно странным, вы думаете, что он предпочел бы не преобразованную перегрузку 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&)
в любом случае, один из способов решить эту проблему-отметить конструктор в тесте как explicit
. Я могу жить с этим. Но самое странное, что если ofstream
заменяется ostream
, то предупреждение исчезнет. Есть идеи почему?
2 ответов
как предупреждение говорит вам, что с ofstream
обе интерпретации требуют преобразования:
ofstream& -> ostream&
наstatic_cast<ostream&>(os) << t.y
,int -> Test
наos << static_cast<Test>(t.y)
если вы используете ostream&
напрямую, то int
-устного перевода требует нет преобразование и, следовательно, является предпочтительным.
когда вы называете
os << t.y;
у вас есть 2 кандидата:
ostream& operator << (ostream&, int) //1
и
ofstream& operator << (ofstream&, Test) //2
нет такого кандидата как
ofstream& operator << (ofstream&, int) //3
согласно правилам разрешения перегрузки, ни 1, ни 2 не лучше для вашего звонка. Отсюда и предупреждение. В случае ostream
, 1, очевидно, лучше подходит, потому что оба аргумента точно совпадают.
лучшее решение-пойти с std::ostream
. Зачем вам нужно перегружать специально для file потоки. Что делать, если вам нужно передать его в строку? Перегрузка оператора выходного потока для std::ostream
(или даже шаблонная версия std::basic_ostream
) и пусть компилятор обрабатывает остальное.