Эффект `basic_streambuf::setbuf`
Моя проблема заключается в следующем: Martin York заявляет, что в этом, этом и этом ответе можно сделать stringstream
читать из некоторого фрагмента памяти, используя basic_stringbuf::pubsetbuf
как это:
char buffer[] = "123";
istringstream in;
in.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); // calls basic_stringbuf::setbuf
int num;
in >> num; // reads 123
К сожалению, я перерыл весь стандарт и не смог увидеть, где он гарантированно будет работать. То, что я вижу, это просто определение реализации. На самом деле на реализацию Microsoft (может быть, на других тоже) этот вызов не влияет.
Вот похожие цитаты, которые я нашел в последнем черновике C++0x. Для basic_streambuf::setbuf
[Streambuf.virt.buffer]:
1 Эффекты: Влияет на потоковую буферизацию способом, который определяется отдельно для каждого класса, полученного из basic_streambuf в этом разделе (27.8.1.4, 27.9.1.5).
2 Поведение по умолчанию: ничего не делает. Возвращает это.
Однако в производных классах поведение, по-видимому, остается определяемым реализацией. За basic_stringbuf::setbuf
он говорит [stringbuf.virtuals]:
1 Эффекты: определяется реализацией, за исключением того, что setbuf(0,0) не имеет эффекта.
За basic_filebuf::setbuf
он говорит [filebuf.virtuals]:
12 Эффекты: если setbuf(0,0) [...], поток становится небуферизованным. В противном случае результаты определяются реализацией. "Небуферизованный" [...]
И это все. Насколько я понимаю, действительная реализация может полностью игнорировать эти вызовы (для ненулевых параметров).
Я ошибся? Как правильно интерпретировать стандарт? Есть ли у C++98/03/0x такие же гарантии? У вас есть больше статистики о том, какие реализации вышеуказанного кода работают, а какие нет? Как basic_streambuf::setbuf
предназначен для использования?
2 ответа
Я считаю, что это определено реализацией и что вы предоставили соответствующие цитаты.
Напомним, что именно об этом и говорится в стандарте COS IOStreams и локали, а не в недавней книге, которую я должен признать, в разделе под названием " Почти семантическая бесплатная функция - setbuf()
":
Функция виртуального члена
setbuf()
является довольно своеобразным элементом буфера потока. Его семантика в основном не определена. Для строковых буферов семантикаsetbuf()
определяются реализацией, за исключением того, чтоsetbuf(0, 0)
определяются: еслиsetbuf(0, 0)
вызывается в потоке раньше, и в этом потоке произошел ввод / вывод, поток становится небуферизованным, что означает, что символы напрямую переносятся в файловую систему и из нее. В противном случае результаты определяются реализацией.Тем не менее, спецификации
setbuf()
заbasic_filebuf
а такжеbasic_stringbuf
вряд ли предъявляют какие-либо требования к семантикеsetbuf()
в других типах потокового буфера. В лучшем случае общая семантика может быть определена как устройство и, в случае пользовательских типов потоковых буферов, зависит от реализации.Отсутствие каких-либо требований освобождает вас от переопределения
setbuf()
практически для любой цели и любым способом, который вписывается в предопределенный интерфейсsetbuf()
,
ХОРОШО. Отвод.
Потратив последние пару дней на изучение документации и внесенных предложений, стало ясно, что это может не сработать (так как это определяется реализацией).
Как вы заметили в своем описании выше:
27.5.2.4.2: 1 Эффекты: Влияет на буферизацию потока способом, который определяется отдельно для каждого класса, полученного из basic_streambuf в этом разделе (27.8.1.4, 27.9.1.5).
Эффект setbuf() действительно определяется его взаимодействием с underflow() 27.8.1.4;
Возвращает: Если входная последовательность имеет доступную позицию чтения, возвращает traits::to_int_type(*gptr()). В противном случае возвращает traits::eof(). Любой символ в базовом буфере, который был инициализирован, считается частью входной последовательности.
Также для получения большего количества символов из потока необходимо проверить 27.9.1.5 showmanyc()
Реализация вполне может обеспечить переопределение для этой сигнатуры функции, если она может определить, что из входной последовательности можно прочитать больше символов.
Что для буфера stringstream означает, что он ничего не получит, так как буфер уже содержит весь поток.
Так что, хотя реализация определена, как она это делает.
Это все еще хорошо определено, как это делает.