Есть ли итератор istream const?

Есть ли такая вещь, как итератор std::istream const?

Следующий код не скомпилируется, поскольку std::istream_iterator в foo() не может привязаться к ссылке const std::istream на временный объект, созданный в main().

// main.cpp
#include <iostream>
#include <sstream>
#include <iterator>

void foo( const std::istream& s )
{
  std::istream_iterator<char> i( s );
  // No std::istream_const_iterator, but anything by another name?
  std::cout << *i;
}

int main( int argc, char* argv[] )
{
  std::string p( "abcdefghijklmnopqrstuvwxyz" );
  foo( std::stringstream(p) );

  return 0;
}

Есть ли итератор istream, который может привязываться к константе istream?

Только что задав этот вопрос, я только что узнал, что istream_iterator ctors инициализируют и выполняют первое чтение. Думаю, мне все еще не ясно: обязательно ли это чтение изменяет связанное istream? Если нет, то кажется, что должен быть какой-то итератор const, который может связываться с константой istream, не так ли?

$ g++ --version
g++ (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -g ./main.cpp && ./a.out
./main.cpp: In function ‘void foo(const istream&)’:
./main.cpp:84:34: error: binding reference of type ‘std::istream_iterator<char>::istream_type&’ {aka ‘std::basic_istream<char>&’} to ‘const istream’ {aka ‘const std::basic_istream<char>’} discards qualifiers
   84 |   std::istream_iterator<char> i( s );
      |                                  ^
In file included from /usr/include/c++/9/iterator:66,
                 from ./main.cpp:80:
/usr/include/c++/9/bits/stream_iterator.h:68:38: note:   initializing argument 1 of ‘std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_iterator(std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type&) [with _Tp = char; _CharT = char; _Traits = std::char_traits<char>; _Dist = long int; std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type = std::ba
sic_istream<char>]’
   68 |       istream_iterator(istream_type& __s)
      |                        ~~~~~~~~~~~~~~^~~

person StoneThrow    schedule 22.04.2020    source источник
comment
Что бы вы сделали с потоком, который является const? Вы никогда не сможете прочитать из него.   -  person cigien    schedule 22.04.2020
comment
@cigien - в этом суть моего вопроса: изменяет ли чтение потока поток или только объект привязки, например. istream_iterator? Ошибка компиляции подразумевает первое, но я пытаюсь узнать/понять, так ли это.   -  person StoneThrow    schedule 22.04.2020
comment
Да, поток модифицируется, когда вы читаете из него. Это в основном итератор ввода.   -  person cigien    schedule 22.04.2020
comment
Короткий ответ: да, чтение из потока изменяет его состояние. Проще говоря, поток отслеживает позицию в некоторой последовательности данных, а чтение из потока сдвигает позицию, представленную итератором потока. В противном случае из потока можно было бы прочитать только одну вещь. Что вам, вероятно, нужно сделать, так это изменить foo(), чтобы принять std:string, создать поток, используя переданную строку (например, как вы делаете в main(), но используя именованную переменную) и читать из потока по мере необходимости. Поток перестанет существовать, когда функция вернется.   -  person Peter    schedule 22.04.2020


Ответы (1)


это чтение обязательно изменяет связанное istream?

Да.

istream_iterator — это удобный класс, который позволяет обращаться с объектами istream так, как если бы они были контейнерами, такими как std::vector или массив.

Ниже istream — это объект, используемый для чтения из потока. И да, чтение из потока изменяет файл istream. Как еще istream будет отслеживать внутреннее состояние, чтобы указать, была ли попытка чтения успешной или нет, сколько символов было прочитано и т. д.?

Поскольку для чтения вам нужны не-const istream объекты, нет смысла создавать istream_iterator из const istream объектов.

person R Sahu    schedule 22.04.2020
comment
Понятно. В любом случае я не знал, пока вы не ответили, но я догадался, что, возможно, итератор привязки содержит метаданные о состоянии чтения файла - очевидно, неверно. Спасибо за просвещение. - person StoneThrow; 22.04.2020
comment
@StoneThrow, пожалуйста. Рад, что смог помочь. - person R Sahu; 22.04.2020