Почему parse_config_file устанавливает бит ошибки в потоке?

Эта минимальная программа использует boost::program_options для разбора файла stringstream. Как ни странно, после синтаксического анализа поток больше не находится в «хорошем» состоянии, и установлены как failbit, так и eofbit.

#include <iostream>
#include <sstream>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

void test_stream(std::stringstream& s);

int main()
{
  using namespace std;
  namespace po = boost::program_options;

  stringstream s;
  s << "seed=3" << '\n';
  test_stream(s);

  po::options_description desc("");
  desc.add_options()
    ("seed", po::value<int>());
  po::variables_map vm;
  po::store(po::parse_config_file(s, desc, true), vm);
  po::notify(vm);

  test_stream(s);

  return 0;
}

void test_stream(std::stringstream& s)
{
  using namespace std;

  if (s.good())
    {
      cout << "stream is good" << endl;
    }
  else
    {
      cout << "stream is not good" << endl;
      if (s.rdstate() & ios_base::badbit)
    cout << "badbit is set" << endl;
      if (s.rdstate() & ios_base::failbit)
    cout << "failbit is set" << endl;
      if (s.rdstate() & ios_base::eofbit)
    cout << "eofbit is set" << endl;
    }
}

Выход:

stream is good
stream is not good
failbit is set
eofbit is set

Хотя условие eof как-то ожидается, так как предположительно синтаксический анализатор прочитал поток до EOF, почему также установлен бит отказа?


person francesco    schedule 13.06.2019    source источник


Ответы (1)


В соответствии с документацией флага ios::eof в некоторых случаях это может произойти:

Операции, которые пытаются прочитать в конце файла, терпят неудачу, и, таким образом, и eofbit, и failbit в конечном итоге устанавливаются. Эту функцию можно использовать для проверки того, вызвана ли ошибка достижением конца файла или какой-либо другой причиной.

Парсер Boost использует std::copy() и итератор в потоке для извлечения параметров. Как указано в ответе Джерри Коффина на другой вопрос, итератор считывает элементы из последовательности. После чтения последнего устанавливается бит eof последовательности. Когда итератор увеличивается еще раз, чтобы получить итератор конца потока, что является условием выхода из цикла в copy(), он снова пытается прочитать, и поэтому также устанавливается бит fail потока.

person user2169513    schedule 18.11.2019