Можно ли сделать чтение входных значений N более элегантным с помощью С++20?

Предположим, я хочу прочитать n целых чисел из стандартного потока ввода. Чтение:

Как прочитать N целых чисел в вектор?

Я считаю, что рекомендуемое решение в основном:

      template<class InputIt, class Size, class OutputIt>
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
{
   for (Size i = 0; i < count && first != last; ++i)
      *result++ = *first++;
   return result;
}

auto read_n(std::istream& is, std::size_t n) {
    vector<int> result;
    // possibly reserve n elements
    copy_atmost_n(
       std::istream_iterator<int>(is),
       std::istream_iterator<int>(),
       n,
       std::back_inserter(result)
    );
    return result;
}

Мне это не нравится по следующим причинам:

  1. Использование copy_atmost_n()делает предположение о том, как отказ от «разыменования» итератора повлияет firstпоследующее значение. Но это предполагаемое поведение является скорее идиосинкразическим, чем общеизвестным. Я уверен, что это смутило бы многих разработчиков.
  2. Нужна "постановочная" переменная.
  3. Повторение std::istream_iterator<int>.

Предоставляет ли C++20 и особенно диапазоны более приятный подход?

Примечание. Нет абсолютной необходимости возвращать std::vector<int>. Также можно использовать некоторую ленивую структуру, если это упрощает задачу.

1 ответ

Ответ должен быть таким:

      auto read_n(std::istream& is, std::size_t n) {
    return std::ranges::istream_view<int>(is) | std::views::take(n);
}

если вы просто хотите ленивый диапазон. А затем собирая это жадно в vector<int>как вы считаете нужным.


Но это пока не совсем работает из-за LWG 3408, но вскоре должно быть исправлено P2259, так что в конечном итоге это будет правильно.

Другие вопросы по тегам