Подтвердить что ты не робот

Почему в стандарте есть как seekpos(), так и seekoff()?

Название в значительной степени говорит обо всем этом.

Я реализую свой собственный класс streambuf, и мне интересно, что думал Комитет, когда они решили включить как std::streambuf::seekpos(), так и std::streambuf::seekoff() (и аналогично для связанных pubseekpos() и pubseekoff()).

Мне кажется, что seekpos(x) должен иметь тот же эффект, что и seekoff(x, std::ios::beg) во всех обстоятельствах, которые я могу себе представить. Но, возможно, мое воображение недостаточно. Итак, почему вы хотите иметь оба, когда seekpos полностью добавляется seekoff? Или, по крайней мере, почему бы вам не сделать реализацию по умолчанию первого, просто вызвать последний?

Если ответ "потому что это то, что сделал STL" или подобное, тогда предположим, что я спрашиваю о обосновании STL или подобного.

(я понимаю, что первым аргументом seekpos является streampos, а первый аргумент seekoff - это streamoff. Но обратите внимание, что 27.4.3.2 [lib.fpos.operations] требует, чтобы позиции потока быть конвертируемым в потоки смещения и обратно, поэтому я не думаю, что это ответ.)

4b9b3361

Ответ 1

Две функции используют разные параметры:

  • seekpos() позиционирует вас в потоке, используя абсолютный streampos положение
  • seekoff() позиционирует вас в потоке, используя относительный streamoff по сравнению с данной позицией (начало, текущий или конец).

Вы совершенно правы: они могут быть преобразованы в обоих направлениях. Но есть тонкая смысловая разница:

  • streampos интуитивно связан с фиксированной позицией, тогда как streamoff как-то связано с движением в файле.
  • вычитая один streampos из другого streampos, делает a streamoff.
  • добавление a streampos в streamoff делает новый streampos.
  • другие комбинации действительны, благодаря простому преобразованию, но требуют большей осторожности.
  • Широкие потоки используют wstreampos для позиции (потому что очевидно, что позиция внутри wchar_t имеет другое значение в качестве позиции в потоке char).
  • но широкие потоки используют streamoff для движения, поскольку это относительное движение по сравнению с позицией.

Если вы используете программирование шаблонов, эти семантические различия более явны с чертами: S::pos_type и S::off_type.

Реальное происхождение

Независимо от этих семантических утилит реальное происхождение этого различия является историческим и связано со стандартной библиотекой C, как объяснил г-н Плагер в в этой статье:

  • streamoff был разработан с fseek() и ftell() стандартной библиотеки C, которые используют long для позиционирование.
  • streampos предназначен для fgetpos() и fsetpos(), которые используют аргумент fpos_t.

Я мог проверить, что это уже было в стандарте C89. Поскольку ни одна из этих функций не упоминалась в исходном K & R, возможно, историк UNIX мог бы рассказать больше о еще более отдаленном пути.

В этой статье объясняются более поздние мысли о стандартном комитете. Похоже, что историческое различие ставится под сомнение и что уже не ясно, действительно ли это необходимо.

Ответ 2

Мне интересно, что думает Комитет, когда они решили включить и std:: streambuf:: seekpos() и std:: streambuf:: seekoff() (и аналогично для связанных pubseekpos() и pubseekoff()).

streampos представляет собой абсолютное положение от начала потока. Таким образом, seekpos() стремится к определенной позиции.

streamoff представляет смещение от заданной позиции. Таким образом, seekoff() может искать относительно любой данной позиции. Вот почему он имеет параметр dir, чтобы указать, как должно интерпретироваться смещение - смещение от начала/конца потока или смещение относительно текущей текущей позиции.

Различные семантики, поэтому предусмотрены различные функции.

Мне кажется, что seekpos (x) должен иметь такой же эффект, как seekoff (x, std:: ios:: beg) в каждом случае, которое я могу себе представить.

Это логично, что он делает, да. Хотя фактическая реализация может быть оптимизирована, например, принимая во внимание текущую позицию, чтобы минимизировать количество физических поисков, особенно для файловых потоков. Не всегда эффективно заставить ОС полностью вернуться к началу файла, чтобы снова двигаться вперед.

Итак, почему вы хотите иметь оба, когда seekpos полностью подпадает к seekoff?

Потому что иногда имеет смысл стремиться к конкретной позиции напрямую, и иногда имеет смысл искать относительное смещение. Это зависит от обстоятельств. Оба случая имеют свои применения.

Итак, почему вы хотите иметь оба, когда seekpos полностью добавляется в seekoff?

Удобство. Зависит от дизайна вызывающего кода, отслеживает ли он абсолютные позиции или относительные смещения.

Или, по крайней мере, почему бы вам не сделать реализацию по умолчанию первого, просто вызвать последнюю?

Это может быть. Это определяется реализацией.

Но обратите внимание, что 27.4.3.2 [lib.fpos.operations] требует, чтобы позиции потоков были конвертированы в потоки смещения и обратно, поэтому я не думаю, что это ответ.)

Кабриолет является ключевым словом здесь. Просто потому, что они могут быть преобразованы друг в друга, это не значит, что они семантически равны друг другу.