Ошибка C ++ при использовании потоковых буферов напрямую с оператором?: - PullRequest
3 голосов
/ 26 февраля 2011

Когда я пытаюсь использовать троичный условный оператор (? :) с перенаправлением буфера потока, gcc выдает ошибку «синтезированный метод, сначала необходимый здесь». В чем проблема и как исправить следующую программу?

#include <fstream>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace std;
    cout << cin.rdbuf();    //OK
    ofstream("tmp.txt") << cin.rdbuf(); //OK

    int i=1;
    (i > 1 ? ofstream("tmp.txt") : cout) << cin.rdbuf(); //Compilation ERROR. Why?
    return 0;
}

скомпилировано с gcc4.4:

...    
/usr/include/c++/4.4/bits/ios_base.h: In copy constructor ‘std::basic_ios<char,   std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’:  
/usr/include/c++/4.4/bits/ios_base.h:790: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private  
/usr/include/c++/4.4/iosfwd:47: error: within this context  
/usr/include/c++/4.4/iosfwd: In copy constructor ‘std::basic_ostream<char,   std::char_traits<char> >::basic_ostream(const std::basic_ostream<char,   std::char_traits<char> >&)’:  
/usr/include/c++/4.4/iosfwd:56: note: **synthesized method** ‘std::basic_ios<char,   std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’   **first required here**   
../item1_1.cpp: In function ‘int main(int, char**)’:  
../item1_1.cpp:12: note: synthesized method ‘std::basic_ostream<char,   std::char_traits<char> >::basic_ostream(const std::basic_ostream<char,   std::char_traits<char> >&)’ first required here   

Ответы [ 3 ]

5 голосов
/ 26 февраля 2011

Это скомпилировано нормально с моей версией clang, я думаю , что это может быть ошибка gcc.

Из моего прочтения стандарта, cout является lvalue типа std::ostream и ofstream("tmp.txt") - это rvalue типа std::ofstream.

Ни один из них не имеет cv-определителей , а std::ostream - этобазовый класс std::ofstream, поэтому условный оператор действителен, а результатом является rvalue и имеет тип std::ostream.

Копирование ни одного из операндов не подразумевается.

, если E1 и E2 имеют тип класса, а базовые типы классов совпадают или один является базовым классом другого: E1 можно преобразовать в соответствие E2, если классT2 - это тот же тип или базовый класс, что и класс T1, а квалификация cv T2 - та же квалификация cv, что и квалификация cv или более высокая квалификация, чем cv-квалификация T1.Если преобразование применяется, E1 изменяется на значение типа T2, которое все еще ссылается на исходный объект класса источника (или соответствующий подобъект).[ Примечание: , то есть копия не создается.]

Используемая вами перегрузка operator<< является членом std::ostream, поэтому нет необходимости связывать временную ссылку с неконстантной ссылкой, элемент может быть вызван для неконстантной ссылки.-const rvalue .

basic_ostream<charT,traits>&
    basic_ostream<charT,traits>::operator<< (basic_streambuf<charT,traits>* sb);

Редактировать

Обратите внимание, что это изменилось в C ++ 0x.Теперь, если результатом условного выражения является rvalue , всегда создается временная копия.Поскольку объекты типа ostream не подлежат копированию, ваш код будет недействительным в C ++ 0x.

См. Здесь: http://www.open -std.org / jtc1 / sc22 / wg21 / docs /cwg_defects.html # 446

1 голос
/ 26 февраля 2011

Вместо этого вы можете использовать условный оператор:

#include <fstream>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace std;
    ofstream file("tmp.txt");
    int i=1;
    (i > 1 ? file : cout) << cin.rdbuf();
    return 0;
}

Это компилируется для меня на gcc 4.4.3.

Я знаю, что вы искали не одну строчку.

ПРИМЕЧАНИЕ : Как указал Эван в своем комментарии, это приведет к созданию файла, даже если он не нужен.

0 голосов
/ 26 февраля 2011

Я вижу две возможности здесь:

  1. cout имеет тип ostream, другой (временный) - ofstream, и они никоим образом не конвертируются друг в друга
  2. , даже если они конвертируемы, результатом является временное значение и оно не будет привязано к оператору <<, так как для него требуется ссылка на неконстантное значение. </li>
...