Временная неконстантная ссылка istream в конструкторе (C ++) - PullRequest
1 голос
/ 09 марта 2010

Кажется, что конструктор, который принимает неконстантную ссылку на istream, не может быть создан с временным значением в C ++.

#include <iostream>
#include <sstream>

using namespace std;

class Bar
{
public:
   explicit Bar(std::istream& is) {}
};

int main()
{
   istringstream stream1("bar1");
   Bar bar1(stream1); // OK on all platforms

   // compile error on linux, Mac gcc; OK on Windows MSVC
   Bar bar2(istringstream("bar2"));

   return 0;
}

Это прекрасно компилируется с MSVC, но не с gcc. Используя gcc, я получаю ошибку компиляции:

g++     test.cpp   -o test
test.cpp: In function ‘int main()’:
test.cpp:18: error: no matching function for call to ‘Bar::Bar(std::istringstream)’
test.cpp:9: note: candidates are: Bar::Bar(std::istream&)
test.cpp:7: note:                 Bar::Bar(const Bar&)

Есть ли что-то философски неправильно во втором способе (bar2) построения объекта Bar? Это выглядит лучше для меня и не требует той переменной stream1, которая нужна только на мгновение.

РЕДАКТИРОВАТЬ : В ответ на комментарий Иоганна Шауба я хотел бы дать немного больше контекста. Во-первых, это не первый раз, когда меня раздражает такое поведение C ++, поэтому я искренне заинтересован в философском обсуждении этого вопроса на более высоком уровне. Тем не менее, в этом конкретном случае у меня есть класс, который читает в файле, который содержит данные, используемые для создания объекта. Мне также нравится писать автоматизированные тесты, которые используют строку вместо файла. Но использование файла для построения является основным вариантом использования. Поэтому я решил создать конструктор, который принимает istream, чтобы я мог использовать либо файл (поток), либо строку (поток). Вот как я сюда попал. Мои тестовые программы создают объекты непосредственно из строк, чтобы имитировать чтение файлов. Это избавляет меня от необходимости создавать отдельные файлы данных для каждого небольшого теста.

Ответы [ 2 ]

3 голосов
/ 09 марта 2010

Именно так в настоящее время работает C ++: вы не можете привязывать неконстантные ссылки к временным объектам. MSVC нестандартен в этом разрешении.

C ++ 0x будет иметь ссылки на r-значения и немного изменит их здесь. Существуют различные философские интерпретации, которые люди пытались применить - для обеих сторон проблемы - но я не нашел такой, которая была бы полностью убедительна. Похоже, что «вам просто нужно выбрать одно поведение и придерживаться его», что объясняет как текущие изменения C ++, так и изменения 0x: выбранное поведение изменилось.

1 голос
/ 09 марта 2010

Роджер прав: это общая политика C ++, которая может связываться только с временными ссылками. Я не думаю, что ссылки на rvalue могли бы вам помочь, потому что в случае передачи временного потока вы do хотите продолжить использовать его измененное состояние.

Более конкретно, почему бы не заменить конструктор friend экстрактором istream &operator>>(istream &s, Bar &b)? Ценой добавления неинициализированного состояния к объекту синтаксис будет еще более C ++ - иш.

...