Подтвердить что ты не робот

Безопасная перегрузка оператора потока >>

Там имеется масса информации о перегрузке operator<<, чтобы имитировать метод toString() -style, который преобразует сложный объект в строку. Я также заинтересован в реализации обратного, operator>> для десериализации строки в объект.

Проверяя источник STL, я понял, что:

istream &operator>>(istream &, Object &);

будет правильной сигнатурой функции для десериализации объекта типа Object. К сожалению, я был в недоумении, как правильно это реализовать - в частности, как обрабатывать ошибки:

  • Как указать недопустимые данные в потоке? Выбросить исключение?
  • В каком состоянии должен быть поток, если в потоке есть искаженные данные?
  • Должны ли какие-либо флаги reset перед возвратом ссылки на цепочку операторов?
4b9b3361

Ответ 1

  • Как указать недопустимые данные в потоке? Выбросить исключение?

Вы должны установить бит fail. Если пользователь потока хочет, чтобы исключение было выбрано, он может настроить поток (используя istream::exceptions), и поток будет выбрасываться соответствующим образом. Я сделал бы это так, тогда

stream.setstate(ios_base::failbit);
  1. В каком состоянии должен быть поток, если в потоке есть искаженные данные?

Для искаженных данных, которые не соответствуют формату, который вы хотите прочитать, вы обычно должны устанавливать бит fail. Для внутренних ошибок, связанных с потоком, используется бит bad (например, если буфер не подключен к потоку).

  1. Должны ли какие-либо флаги reset перед возвратом ссылки на цепочку операторов?

Я не слышал об этом.


Чтобы проверить, находится ли поток в хорошем состоянии, вы можете использовать класс istream::sentry. Создайте его объект, передав поток и true (чтобы он не пропустил пробел сразу). Часовой будет оценивать до false, если бит eof, fail или bad установлен.

istream::sentry s(stream, true);
if(!s) return stream;
// now, go on extracting data...

Ответ 2

Некоторые дополнительные примечания:

  • при реализации оператора → , вам, вероятно, следует рассмотреть возможность использования bufstream, а не другие перегрузки оператора → ;

  • исключения, возникающие во время операции, должны быть переведены на failbit или badbit (члены streambuf могут бросать, в зависимости от класс);

  • настройка состояния может бросить; если вы установили состояние после исключение, вы должны распространять исходное исключение, а не одно выбрано setstate;

  • ширина - это поле, на которое вы должны обратить внимание. Если ты учитывая это, вы должны reset его равным 0. Если вы используете другие оператор → делать базовые работы, вам нужно вычислить ширину, которую вы передаете от того, которое вы получили;

  • подумайте о том, чтобы учитывать локаль.

Lange и Kreft (стандартные IOStreams и локали С++) конвертируют это в четное более подробно. Они дают код шаблона для обработки ошибок, который принимает около одной страницы.

Ответ 3

Что касается флагов, я не знаю, есть ли какой-либо стандарт где-то, но это хорошая идея для reset их.

Boost имеет опрятные обтекатели raii для этого: IO State Savers