Ответ 1
Я думаю, что операторы выделения потоков могут быть очень полезны в сочетании с алгоритмами STL, такими как std::copy
и с классом std::istream_iterator
.
Прочитайте этот ответ, чтобы узнать, о чем я говорю.
Я написал тонны функций operator<<(std::ostream &, const T &)
- они невероятно полезны.
Я никогда не писал функцию operator>>(std::istream &, T &)
в реальном коде или даже использовал операторы извлечения для встроенных типов (ОК, возможно, для std::string
). Являются ли они подходящими только для коротких примеров программ и учебников? Является ли operator>>
неудачной функцией С++?
Были заданы вопросы о безопасном перегрузке операторов потоков. Что мне интересно, если кто-то делает это на практике.
Даже для чего-то простого, такого как чтение ввода из файла в С++, я не могу предложить использовать operator>>
. Слишком сложно написать код, который является надежным при обнаружении и обработке ошибок во вводе (или я не знаю, как это сделать).
Если вы не согласны, пожалуйста, покажите хороший пример использования operator>>
- возможно, отвечая на этот последний вопрос, с которым я связан.
op>>
, поэтому я принял это.
Я думаю, что операторы выделения потоков могут быть очень полезны в сочетании с алгоритмами STL, такими как std::copy
и с классом std::istream_iterator
.
Прочитайте этот ответ, чтобы узнать, о чем я говорю.
Да, я использую оператор → (хотя не так часто, как оператор < <). Это очень полезно для анализа пользовательских типов в их соответствующих объектах и, следовательно, для централизации анализа и необходимой обработки ошибок. Это также очень полезно для синтаксического анализа строкового представления перечислимого типа.
Например, рассмотрим перечисляемый тип, представляющий плод. Вы можете использовать оператор → для анализа строки (например, "яблоко", "банан" и т.д.), Чтобы получить правильное значение перечисления.
std::istream &operator>>(std::istream &is, Fruit &fruit)
{
std::string str;
is >> str;
if (str == "apple")
fruit = APPLE;
else if (str == "banana")
fruit = BANANA;
// other fruits
else
is.setstate(std::ios::failbit);
return is;
}
Обратите внимание также на использование метода setstate в istream для установки состояния сбоя потока при обнаружении неизвестной строки. При использовании этого оператора вы можете проверить состояние отказа в потоке следующим образом:
Fruit fruit;
std::cin >> fruit;
if (std::cin.fail())
std::cout << "Error: Unknown Fruit!" << std::endl;
Значения чаще печатаются, чем чтение, поэтому operator<<
используется чаще, чем operator>>
. Тем не менее, если вы хотите читать значения, полезно использовать operator>>
.
То, что вы должны проверять наличие ошибок, не относится к operator>>
, очевидно, что любой другой способ чтения значений должен каким-то образом обнаруживать недопустимый ввод.
Я никогда их не пишу и редко использую "встроенные". Операторы извлечения довольно бесполезны для чтения интерактивных пользовательских вводных данных, потому что слишком непросто для потока работать плохо. Написание пользовательской процедуры синтаксического анализа почти всегда проще и надежнее. И когда дело доходит до сериализации, если я хочу что-то сохранить как текст, я делаю это в стандартном формате, таком как XML, который операторы извлечения явно не подходят для чтения. В противном случае я храню данные в базе данных или в двоичном файле, что еще раз плохо подходит для использования с экстракторами.
operator>>
полезен при преобразовании чисел в текстовой форме во внутреннее представление.
Он также может быть полезен при загрузке данных для объектов. В отличие от scanf
, которые не могут быть перегружены для разных типов, объекты могут перегружать operator>>
. Таким образом, он обеспечивает больше данных, скрывающихся для загрузки объектов, внутреннее представление не обязательно должно быть известно для чтения данных в объект.
Оператор → - это в основном десериализация. В моем ограниченном и анекдотическом опыте большинство сериализации/десериализации в С++ реализовано на более низком уровне, чем библиотека потока. Он не должен быть реализован на более низком уровне - он обычно есть.
Реализация пользовательской десериализации не всегда является тривиальной проблемой, но вы, вероятно, столкнетесь с теми же проблемами, даже если вы не реализуете ее с синтаксисом извлечения потока.
Здесь используется чистое использование оператора извлечения потока, который, по крайней мере, минимально полезен: http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
В этой ограниченной области, кажется, правильное использование довольно просто.
Я сильно использовал оператор < для сборки списков инструкций сортировки, полей в представлениях базы данных и т.д. в моем API OOFILE.
По какой-то причине большое количество пользователей посчитало интуитивным использование оператора → в добавить поле сортировки, которое было обратным видом. Я не знаю, кто предложил это в первую очередь, но он обратился к достаточно людям, которые сделали это в API.
например:
dbSorter arcSort; // declare a sorter
arcSort << reverse(Date) << FileName; // "normal" way to specify two sort fields
arcSort >> Date << FileName; // shorthand way that evolved to specify
Мы также использовали обычное использование оператора → для синтаксического анализа всего dbTable из потока.