Conditions for casting stream_buffer to std::basic_streambuf

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::streamis 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.
participants (1)
-
Tyler Weston