Эффект `basic_streambuf:: setbuf`

Моя проблема такова: Мартин Йорк утверждает этот, this, а this отвечает, что можно сделать 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 (возможно, и на других) этот вызов не имеет эффекта.

Вот ссылки, которые я нашел в последнем проекте С++ 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) [...], поток становится небуферизованным. В противном случае результаты реализованы. "Небуферизованный" [...]

И что это. Как я вижу, допустимая реализация может полностью игнорировать эти вызовы (для ненулевых параметров).

Неужели я ошибаюсь? Какова правильная интерпретация стандарта? У С++ 98/03/0x есть те же гарантии? У вас есть больше статистических данных о том, какие реализации работает над этим кодом, а на каких нет? Как использовать basic_streambuf::setbuf?

Ответ 1

Я считаю, что это реализация определена и что вы предоставили соответствующие кавычки.

Для записи это то, что Стандартные IOStreams и локали С++, а не совсем недавняя книга, которую я должен признать, должен сказать на в разделе под названием " Почти семантическая свободная функция - setbuf()":

Действительная функция-член setbuf()является довольно своеобразным буфером потока член. Его семантика в основном undefined. Для буферов струнных потоков, семантика setbuf()определенными реализацией, за исключением того, что setbuf(0, 0) определены: if setbuf(0, 0) вызывается в потоке до и ввода/вывода на этом поток, поток становится небуферизованным, что символы непосредственно транспортируется в файл и из него система. В противном случае результаты реализации.

Однако характеристики setbuf() для basic_filebuf и basic_stringbuf вряд ли навяжут требования к семантике setbuf() в другом буфере потока типы. В лучшем случае общая семантика может быть определено как устройство, а в случай пользовательского буфера потока типы, специфичные для реализации.

Отсутствие каких-либо требований освобождает вас переопределить setbuf() для любой цели и любым способом, который подходит в предопределенный интерфейс setbuf().

Ответ 2

OK. Отвод.

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

Как вы заметили в своем описании выше:

27.5.2.4.2: 1 Эффекты: влияет на буферизацию потока таким образом, который определен отдельно для каждого класса, производного от basic_streambuf в этом разделе (27.8.1.4, 27.9.1.5).

Эффект setbuf() действительно определяется его взаимодействием с 27.8.1.4 underflow();

Возвращает: Если входная последовательность имеет доступную позицию чтения, возвращает черты:: to_int_type (* gptr()). В противном случае возвращаются черты:: eof(). Любой символ в базовом буфере, который был инициализирован, считается частью входной последовательности.

Также для получения большего количества символов из потока вам нужно проверить 27.9.1.5 showmanyc()

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

Что для буфера stringstream означает, что он ничего не получит, поскольку буфер уже содержит весь поток.

Итак, хотя это реализация определена как она это делает.
Он все еще четко определен, как он это делает.