предупреждение о неоднозначности для ofstream, но не для ostream. Какая разница? - PullRequest
7 голосов
/ 19 декабря 2011

Это не важно.Но мне любопытно, когда появится это предупреждение.Мой настоящий вопрос заключается в том, почему 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 с именем ty, или я хочусначала преобразовать 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&)
* 1017В любом случае, один из способов решения этой проблемы - пометить конструктор в Test как explicit.Я могу жить с этим.Но странная вещь в том, что если ofstream заменить на ostream, то предупреждение исчезнет.Есть идеи почему?

Ответы [ 2 ]

7 голосов
/ 19 декабря 2011

Когда вы звоните

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.Зачем вам нужно перегружать специально для файловых потоков.Что делать, если вам нужно передать его в строку?Перегрузите оператор выходного потока для std::ostream (или даже для шаблонной версии std::basic_ostream) и дайте компилятору обработать все остальное.

5 голосов
/ 19 декабря 2011

Как говорится в предупреждении, при ofstream обе интерпретации требуют преобразования:

  1. ofstream& -> ostream& в static_cast<ostream&>(os) << t.y,

  2. int -> Test in os << static_cast<Test>(t.y)

Если вы используете ostream& напрямую, тогда интерпретация int требует преобразования no и, следовательно, является предпочтительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...