каков результат увеличения istream_iterator, который уже находится в конце потока? - PullRequest
0 голосов
/ 20 августа 2009

Я посмотрел на стандарт и не увидел очевидного ответа.

предположим, я сделал это:

std::istream_iterator<char> is(file);
while(is != std::istream_iterator<char>()) {
    ++is;
}

сейчас is находится в конце потока и равно std::istream_iterator<char>(). Что произойдет, если я увеличу его еще раз? Это все еще равно std::istream_iterator<char>()? или результат не определен?

Стандарт прямо заявляет, что *is является неопределенным поведением, если is находится в конце потока. Но я ничего не видел относительно итерации за пределами конца потока ...

EDIT

Я спрашиваю, потому что я наткнулся на некоторый код, который делает что-то вроде этого:

// skip 2 input chars
++is;
++is;
if(is != std::istream_iterator<char>()) {
    // continue using is and do some work...but what if the first
    // increment made it EOS? is this check valid?
}

Ответы [ 2 ]

4 голосов
/ 21 августа 2009

Таблица 72 в C ++ 03 о требованиях итератора ввода говорит, что предварительным условием ++r является то, что r не может ссылаться. Те же самые предварительные условия выполняются для r++.

Теперь 24.5.1/1 говорит о istream_iterator

Результат operator* в конце потока не определен.

В заключение, влияние operator++ на итератор конца потока не определено.

Таблица 72 в C ++ 03 о требованиях к итераторам ввода говорит, что предварительным условием ++r является то, что r не может ссылаться. Те же самые предварительные условия выполняются для r++.

Теперь 24.5.1/1 говорит о istream_iterator

Результат operator* в конце потока не определен.

В заключение, влияние operator++ на итератор конца потока не определено.


Заметьте, что я думаю, что этот вывод делает поведение неопределенным только тогда, когда вы пишете или используете алгоритм, использующий входные итераторы, которые демонстрируют это поведение, а затем пропускают итератор istream. Только из с использованием явного самого итератора istream, не рассматривая его как входной итератор и полагаясь на его инварианты, я думаю, что приведенный выше вывод не совсем верен (у нас может быть класс, который не требует например, r разыменовывается).

Но, глядя на то, как описан итератор istream, вызов operator++ после достижения значения конца потока также приводит к неопределенному поведению. operator== для него определяется как эквивалент

x.in_stream == y.in_stream

Где in_stream - указатель на поток, перебранный и представленный в стандартном тексте для определения поведения и семантики «только для представления». Теперь единственная реализация, о которой я могу подумать, которая делает эту работу, - это использование итератора конца потока, который хранит в качестве указателя потока нулевой указатель. Но operator++ определяется как выполнение чего-то, что имеет следующий эффект

*in_stream >>value

Теперь, если вы войдете в состояние конца потока, и мы установим для in_stream нулевой указатель, то, несомненно, результатом этого будет неопределенное поведение.

Таким образом, даже если вы используете только итератор istream, нет никаких гарантий, что вы можете увеличить значение после конца потока.

3 голосов
/ 20 августа 2009

Если оно не определено, оно не определено :-) В стандартных (последний черновик C ++ 0X) словах мой акцент:

неопределенное поведение

поведение, которое может возникнуть при использовании ошибочной конструкции программы или ошибочных данных, для которого этот международный стандарт не предъявляет никаких требований. Также можно ожидать неопределенного поведения когда это Международный стандарт опускает описание любого явного определения поведения.

...