1
votes

I'm trying to get familiar with using boost::iostreams. Looking at the iostreams tutorial, it seems this test code ought to be a trivial implementation of a sink device and the stream template:

#include <iostream>
#include <iosfwd>

#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/concepts.hpp>

namespace io = boost::iostreams;

class testSink {
public:
    typedef char            char_type;
    typedef io::sink_tag    category;

    std::streamsize write(const char* s, std::streamsize n) {
        std::cout.write(s, n);
        return n;
    }
};

int main(int argc, char *argv[])
{
    io::stream<testSink>    out;
    out << "Hello" << std::endl;
    return EXIT_SUCCESS;
}

Compiling this under linux and g++ (g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)) succeeds without error, but running it crashes with an assertion failure:

/usr/local/include/boost/iostreams/detail/optional.hpp:55: T& boost::iostreams::detail::optional::operator*() [with T = boost::iostreams::detail::concept_adapter]: Assertion `initialized_' failed. Aborted (core dumped)

There is obviously some undocumented initialization step, but what?

Thanks

2

2 Answers

0
votes

The missing initialization step was calling "open". The boost documentation doesn't seem too clear on that -- I figured that out from reading the source. In fact, the example in the documentation I'm using (1.55) has the same problem you're facing.

Here's how I modified testSink for you: I added a constructor that takes a reference to an ostream and then passed std::cout to the open() method.

class testSink {
public:
    typedef char            char_type;
    typedef io::sink_tag    category;

    testSink(std::ostream &out) : out_(out) { }

    std::streamsize write(const char* s, std::streamsize n) {
        out_.write(s, n);
        return n;
    }

private:
    std::ostream& out_;
};

And then this is the main function:

io::stream<testSink>    out;
out.open(std::cout);
out << "Hello" << std::endl;
0
votes

I ran into the same issue, and calling the non-default constructor of the stream object passing a sink object solved it (according to the documentation, the non-default constructor creates a stream which is ready to perform i/o).

So your example works with the following change to the main function:

int main(int argc, char *argv[])
{
    testSink t;
    io::stream<testSink>    out(t); // <---- call non-default constructor passing a testSink object
    out << "Hello" << std::endl;
    return EXIT_SUCCESS;
}

Here's the example working on Coliru.