Я пишу собственный оператор >>
, который считывает весь символ потока за символом и обновляет объект каждым символом, примерно так:
class MyClass
{
public:
bool Process(char c);
}
std::istream& operator>>(std::istream& input, MyClass& value)
{
if (input)
{
char c;
bool parsing_success = true;
while (parsing_success && input >> c)
{
parsing_success = value.Process(c)
}
if (!parsing_success)
input.setstate(std::ios_base::failbit);
}
return input;
}
Идея в том, что поток читать символ за символом, пока не будет достигнут конец потока или пока не встретится символ, который MyClass
не нравится. В последнем случае оператор выдаст ошибку.
Я собираюсь использовать его следующим образом:
MyClass value;
if (std::cin >> value)
{
//do something with value
}
else
{
//handle error
}
Проблема, с которой я сталкиваюсь, заключается в том, что после всего поток читается, istream::fail()
возвращает true, потому что был достигнут конец потока, что устанавливает как eof
, так и fail
(как показано в других вопросах, таких как this ).
В результате std::cin >> value
возвращает false, даже если поток был успешно обработан.
Теперь вызывающий оператор потенциально может проверить, установлен ли бит eof
, но я чувствую как это не идиоматия c с другими стандартными шаблонами использования оператора >>
- например, int x; if (cin >> x) { //do something }
.
Итак, мой вопрос - Должен ли я вызывать istream :: clear после успешного обработка потока? . Что-то вроде этого:
if (!parsing_success)
input.setstate(std::ios_base::failbit);
else
input.clear();
Это очистит бит отказа и гарантирует, что std::cin >> value
вернет false только в случае допустимой ошибки потока или при обнаружении недопустимого символа. Однако я просто не уверен, что это идиоматия c C ++ или вызовет другие проблемы.
Спасибо!