Кто-нибудь на самом деле использует операторы извлечения потока?
Я написал тонны operator<<(std::ostream &, const T &)
функции - они невероятно полезны.
Я никогда не писал operator>>(std::istream &, T &)
функции в реальном коде или даже использовали операторы извлечения для встроенных типов (ОК, может быть, для std::string
). Подходят ли они только для коротких примеров программ и учебников? Является operator>>
неудачная особенность C++?
Были заданы вопросы о безопасной перегрузке потоковых операторов. Что мне интересно, так это если кто-то делает это на практике.
Даже для чего-то простого, такого как чтение ввода из файла в C++, я не могу предложить использовать operator>>
, Слишком сложно писать код, который был бы надежным в обнаружении и обработке ошибок при вводе (или я не знаю как).
Если вы не согласны, пожалуйста, покажите хороший пример использования operator>>
- возможно, ответив на последний вопрос, с которым я связан.
Заключение: Спасибо всем за ответы, много хороших мнений. Ответ Мануэля заставил меня пересмотреть свое нежелание использовать
op>>
поэтому я принял это.
7 ответов
Я думаю, что операторы потокового извлечения могут быть очень полезны в сочетании с алгоритмами 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>>
, Таким образом, он обеспечивает больше скрытия данных для загрузки объектов, внутреннее представление не нужно знать, чтобы считывать данные в объект.
Оператор >> это в основном десериализация. По моему ограниченному и неподтвержденному опыту, большая часть сериализации / десериализации в C++ реализована на более низком уровне, чем потоковая библиотека. Это не должно быть реализовано на более низком уровне - это просто так.
Реализация пользовательской десериализации не всегда тривиальная проблема, но вы, вероятно, столкнетесь с теми же проблемами, даже если вы не реализуете ее с синтаксисом извлечения потока.
Вот легкомысленное использование оператора извлечения потока, которое по крайней мере немного полезно: http://www.parashift.com/c++-faq-lite/misc-technical-issues.html
В этом ограниченном объеме кажется, что правильное использование довольно просто.
Я интенсивно использовал operator<< для сборки списков инструкций сортировки, полей в представлениях базы данных и т. Д. В моем 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 из потока.