Hi All,

How do you construct an std::ostream from a boost::iostreams::stream_buffer<io::back_insert_device<...> > ? Is this not possible with a simple sink_tag for the category?

I'm using libpng and want to abstract writing to a file directly or to a memory buffer. libpng provides hooks for write and flush functions, and never seeks. I implemented these functions for std::ostream and it works great for file writing. My assumption that it would be trivial to provide a std::ostream to a memory buffer turned out to be incorrect.

Unfortunately type information is lost through libpng as you have to pass your io data as void*, which makes using templatized stream classes difficult. In the tutorial for iostreams it says: "The template io::stream is provided as a convenience. It's always possibly to avoid io::stream and simply use io::stream_buffer together with one of the standard library stream templates."

I tried following this pattern, and it works great for files:

        io::file_sink sink(filename, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
        io::stream_buffer<io::file_sink> streamBuf(sink);
        std::ostream pngStream(&streamBuf);

However, I am having problems providing an ostream for the memory buffer case.

        shared_ptr<vector<char> > vec(new vector<char>());
        io::back_insert_device<vector<char> > sink(*vec);
        io::stream_buffer<io::back_insert_device<vector<char> > > streamBuf(sink);
        std::ostream pngStream(&streamBuf);

This snippet produces the following error in msvc 9 with boost 1.45.

2>error C2664: 'std::basic_ostream<_Elem,_Traits>::basic_ostream(std::basic_streambuf<_Elem,_Traits> *,bool)' : cannot convert parameter 1 from 'boost::iostreams::stream_buffer<T> *' to 'std::basic_streambuf<_Elem,_Traits> *'
2>        with
2>        [
2>            _Elem=char,
2>            _Traits=std::char_traits<char>
2>        ]
2>        and
2>        [
2>            T=boost::iostreams::back_insert_device<std::vector<char>>
2>        ]
2>        and
2>        [
2>            _Elem=char,
2>            _Traits=std::char_traits<char>
2>        ]
2>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

I noticed file_sink::category has more tags than back_insert_device::category, so I took the container_device in the tutorial and implemented all the tags that file_sink has, and still get the same error. Digging farther I see that basic_file::impl contains an actual std::basic_filebuf which can be casted to basic_streambuf. The basic_filebuf is private member of a private member, so shouldn't be accessible for normal casting and I don't see the cast explicitly provided. How does the file_sink to basic_streambuf cast work? How can I implement this cast for container_device without inheriting and overriding all of the methods of basic_streambuf?

 Is there an abstract parent class to boost::iostreams::stream or stream_buffer that allows for polymorphism to ease the pain of the required void* cast? I'm still relatively new to metaprogramming patterns.

As a side note, the tutorial continues to suggest default-constructing a std::ostream, which is not possible at least with msvc's std implementation.