1

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

Raxvan
  • 6,257
  • 2
  • 25
  • 46
E. Hildum
  • 11
  • 1

2 Answers2

0

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;
Jason
  • 1,086
  • 5
  • 10
  • Hm. OK, maybe I'll dig into the source too. For my eventual target project, I'd prefer not to pass in an ostream reference. I'll have to see what open() overloads are available. Thanks for your response. – E. Hildum Mar 27 '18 at 21:29
0

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.