Почему в стандарте есть как 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] требует, чтобы позиции потока быть конвертируемым в потоки смещения и обратно, поэтому я не думаю, что это ответ.)
Ответы
Ответ 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] требует, чтобы позиции потоков были конвертированы в потоки смещения и обратно, поэтому я не думаю, что это ответ.)
Кабриолет является ключевым словом здесь. Просто потому, что они могут быть преобразованы друг в друга, это не значит, что они семантически равны друг другу.