Какие гарантии существуют при чередовании чтения и записи?

При работе с С++ std::iostream (например, std::fstream или std::stringstream) стандартная ли гарантия что-либо связана с отношениями между чтениями и записью, выполненными в одном потоке? То есть, обязательно, верно, что если Я пишу данные в std::fstream, а затем попытаюсь прочитать данные из этого потока, я должен увидеть данные, которые я написал? Как насчет для std::stringstream? В качестве примера это гарантированно работает?

std::stringstream myStream;
myStream << "137 Hello 2.71828";

int myInt;
std::string myString;
double myDouble;

myStream >> myInt >> myString >> myDouble; // Parse as expected?

А как насчет этого случая?

std::fstream myStream("some-file.txt", ios::in | ios::out);
myStream << "137 Hello 2.71828";

int myInt;
std::string myString;
double myDouble;

myStream >> myInt >> myString >> myDouble; // Parse as expected?

Я спрашиваю, потому что недавно я разработал сетевой потоковый класс, в котором чтения и записи не влияют друг на друга (поскольку считывает данные из сети и записывает отправку по сети). То есть, записывая

myNetworkStream << "Hi there!" << endl;

записывается по сети, а

myNetworkStream >> myValue;

читается из сети. Я не уверен, что это поведение согласуется с общим контрактом на потоки. Если бы я должен был догадаться, возможно, имеет место один из следующих трех:

  • Контракт iostream ничего не говорит о чередовании чтения и записи или
  • В общем случае контракт iostream ничего не говорит о чередовании чтений и записей, но в спецификации, как стандартные типы, такие как fstream и stringstream, работают специальные предписания, или
  • Контракт iostream говорит что-то о чередующихся чтениях и записи, что нарушает класс сетевого потока.

У меня есть копия спецификации, но секция по потокам настолько плотная и загадочная, что ее невозможно, но невозможно. Если бы кто-то мог прояснить, как именно iostream должен вести себя, когда вы смешиваете чтения и записи, я бы очень признателен.

Ответ 1

Я не уверен в главе и стихе стандарта С++ (которого у меня нет, чтобы проверить), но я очень хорошо знаком с C стандарт по этому вопросу (который у меня есть).

C99 заявляет, что поток можно открыть в режиме чтения, записи или обновления. Только последний режим позволяет как чтение, так и запись в один поток, но (цитата):

... вывод не должен сопровождаться вводом без промежуточный вызов функции fflush или функции позиционирования файла (fseek, fsetpos, или rewind), и вход не должен сопровождаться выходом без промежуточный вызов функции позиционирования файла, если только операция ввода не встречается конец файл.

Я бы предположил, что стандарт С++ говорит что-то подобное где-то: вы должны сбросить или переместить поток до "реверсирования" в направлении чтения/записи.

Изменить: На самом деле есть два отдельных указателя, которые можно запросить с помощью basic_istream::tellg и basic_ostream::tellp. Однако я нашел упоминание о возможности того, что два не указывают на одно и то же положение в потоке только в связи с stringstream, а не на fstream. Взятый вместе с вышеприведенным утверждением, это имеет смысл именно так. Все еще не могу указать на главу и стих стандарта, хотя, извините.