Зачем boost :: iostream :: filtering_ostream с использованием boost :: iostreams :: zlib_compressor должен быть уничтожен для записи приемника? - PullRequest
0 голосов
/ 21 марта 2019

Потратив довольно много времени на отладку проблемы сегодня, я заметил, что boost::iostream::filtering_ostream необходимо уничтожить, чтобы записать приемник.

Тестовый код:

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>

#include <sstream>

struct ZlibOstream : boost::iostreams::filtering_ostream
{
    ZlibOstream(std::ostream& os)
    {
        boost::iostreams::filtering_ostream::push(boost::iostreams::zlib_compressor{});
        boost::iostreams::filtering_ostream::push(os);
    }
};

int main()
{   
    std::ostringstream oss;

    #ifdef HAS_SCOPE
    {
    #endif

    ZlibOstream zlibOstream{oss};

    zlibOstream << "This is a test string.\n";

    #ifdef HAS_SCOPE
    }
    #endif

    return (oss.tellp() == 0);
}

Вызов flush() не помогает, и мне не нужно это делать, когда я удаляю zlib_compressor.

Результат с coliru: https://coliru.stacked -crooked.com / a / 7cd166d2d820e838

В чем причина такого поведения?

1 Ответ

0 голосов
/ 22 марта 2019

Это на самом деле связано с этим вопросом:

Сброс наддува :: iostreams :: zlib_compressor. Как получить «синхронную очистку»?

Вам нужен вызов на boost::iostreams::zlib_compressor::close, чтобы произошел сброс.

Вы можете достичь этого, позвонив либо pop(), либо reset() на boost::iostream::filtering_ostream.

Обратите внимание, pop(), как следует из названия, вставляет последний фильтр в цепочке и reset() полностью очищает цепочку, так что filtering_ostream не будет использоваться впоследствии.

Пример:

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>

#include <sstream>

struct ZlibOstream : boost::iostreams::filtering_ostream
{
    ZlibOstream(std::ostream& os)
    {
        boost::iostreams::filtering_ostream::push(boost::iostreams::zlib_compressor{});
        boost::iostreams::filtering_ostream::push(os);
    }
};

int main()
{   
    std::ostringstream oss;

    ZlibOstream zlibOstream{oss};

    zlibOstream << "This is a test string.\n";

    zlibOstream.reset(); // needed if you want to write to oss

    return oss.tellp();
}
...