The basic_outbuf abstract class template provides a thin, simple and lightweight abstraction over output streams that can be used in freestanding C++ implementations.

Note
This library does not belong to the Boost C++ libraries. Maybe some day it will be there.

1. Overview

1.1. Rationale

Suppose you want to implement an encoder. Let’s say to Base64. That should be a simple task, right? But it turns out that is hard to find the ideal design. Let’s consider a function that returns a string object:

std::string to_base64(const std::byte* src, std::size_t count);

It’s simple and easy to use. But it has an extra cost of a heap allocation, which some users may dislike.

An alternative is to use std::ostream:

void to_base64(std::ostream& dest, const std::byte* src, std::size_t count);

However such function is complex to use. The user needs to implement a class that derives from ostream to customize the destination. It’s a complex task for most C++ programmers.

Also, std::ostream and std::string are not available in freestanding C++ implementations. Thus they should be avoided if you want your function to usable in the widest range of environments.

So, you may think, let’s adopt the C-style:

bool to_base64( char** dest
              , char* dest_end
              , const std::byte** src
              , const std::byte* src_end );

This way the user would need to successively call to_base64 until the whole input is read. Besides the inconvenience, this still has a important limitation: sometimes the input is not available as an array of bytes. Sometimes it is lazyly avaluated. For example, suppose you have a class Image that has member functions that encodes to different image formats:

class Image
{
public:
    // ...

    /* ??? */ to_jpeg( /* ??? */ ) const;
    /* ??? */ to_bmp( /* ??? */ ) const;
    /* ??? */ to_png( /* ??? */ ) const;
};

Now how do you design the all these functions, such that one could convert an image to JPEG, and then to Base64? What signatures should they have ?

The basic_outbuf abstract class template aims to solve the puzzle. Now you can declare to_jpeg like this:

    void to_jpeg(boost::basic_outbuf<std::byte>& dest) const;

And, instead of a function, you can design the Base64 encoder as a class that derives from basic_outbuf and that would hold a reference to another basic_outbuf as the further destination.

Image image;
// edit the image ...

// encode the image:
Base64Encoder base64encoder{some_destination};
image.to_jpeg(base64encoder);
encoder64encoder.finish();

With the same pattern you could design, for instance, an encrypter. So you can convert the image to JPEG, then encrypt it, then convert to it Base64, then insert it into some a JSON output, then send it to …​ whatever. You got the idea: composability, free of heap allocation and support to lazy evaluation. All this with a simple class template defined in ligthweight to compile header file, and that can be used in a freestanding implementation.

1.2. How to write into an outbuf object

1.2.1. Low-level writing

The member functions pos() and end() define the memory region where you can write. If the space is too small, you can call the recycle virtual function. It will consume the content written so far since the last call and reset the buffer positions. recycle() ensures that the new space afterwards is at least equal to min_size_after_recycle<char_type>(), which is at least equal to 64. If you need more space than that, then you have to find a way to break your content down into smaller parts or you have to use an intermediate buffer.

After you write anything to pos() you need to call advance or advance_to. They cause the value returned by pos() to be incremented.

#include <boost/outbut.hpp>

void get_message(boost::basic_outbuf<char>& dest)
{
    if (dest.end() - dest.pos() < 5)
    {
        dest.recycle();
    }
    std::strcpy(dest.pos(), "Hello");
    dest.advance(5);
    // ...
}

The code above can be rewriten like this:

#include <boost/outbut.hpp>

void get_message(boost::basic_outbuf<char>& dest)
{
    dest.require(5);
    std::strcpy(dest.pos(), "Hello");
    dest.advance(5);
    // ...
}

dest.require(s) does just that: it calls recycle if the the available buffer’s space is less than s.

The range [pos(), end()) is always a valid accessible memory area. So it is always safe to write things there. However, you should occasionally check whether the outbuf is in "good" state. You do that with the good member function. If it returns false, then it means that writing into the buffer has no relevant side effect and it’s a mere waste of CPU resources. The state may change from good to bad when recycle is called. It never changes from bad to good.

1.2.2. The write and put function templates

If you want to write an array of characters, you can use the write function template, that writes it in a piecewise way, taking care to never write beyond the buffer’s end and calling recycle() whenever necessary.

boost::basic_outbuf<char> ob& = /* ... */;
string_view str = /* ... */;
boost::write(ob, str.begin(), str.end());

See also the put function template that inserts a single character.

1.2.3. Inserting formatted data

basic_outbuf does not support formatting. But since you have direct access to the buffer, you could use std::to_chars and std::sprintf though that would require from you to constantly check whether the buffer’s size is adequate.

However if can use {fmt} ( or <format> , available in C++20 ), you can insert formatted data through an output iterator adapter:

#include <boost/outbuf/iterator.hpp>
#include <fmt/format.h>

int sample(boost::basic_outbuf<char>& ob) {
    boost::outbuf_iterator<char> it{ob};
    fmt::format_to(it, "ten = {}, and twenty = {}.", 10, 20)
}

outbuf_iterator calls recycle() whenever is necessary, so that you don’t need to constantly check the buffer’s available space.

1.3. The basic_outbuf_noexcept class template

The basic_outbuf_noexcept class template derives from basic_outbuf, and it has the exact same members. The only difference is that basic_outbuf_noexcept<CharT>::recycle() is noexcept.

Consider a function that takes a basic_outbuf reference as paramenter an forwards it to another module. Sometimes we can’t allow exceptions crossing modules' boundaries. So that’s an example of when a one rather use basic_outbuf_noexcept.

1.4. The underlying_outbuf class template

basic_outbuf<CharT> derives from underlying_outbuf<sizeof(CharT)>. The inheritance is private to force you to call as_underlying() member function to cast an basic_outbuf reference to underlying_outbuf, because it’s good to prevent implicit cast in this case.

To understand the purpose of underlying_outbuf, suppose you want to implement a function that converts UTF-32 to UTF-8, and, of course, you want to use basic_outbuf to handle the output. Now, there are different character type that can represent UTF-8: char, char8_t, std::byte, unsigned char …​ So you face dilemma of which one to adopt:

void utf32_to_utf8( boost::outbuf::basic_outbuf</* ??? */>& destination
                  , const char32_t* src
                  , std::size_t src_size );

Actually, the caller should ideally decide that. So you may consider implement utf32_to_utf8 as template:

template <typename CharT>
void utf32_to_utf8( boost::outbuf::basic_outbuf<CharT>& destination
                  , const char32_t* src
                  , std::size_t src_size );

But templates have their disadvantages, and sometimes we want or need to avoid them. That’s the reason the underlying_outbuf class template exists.

void utf32_to_utf8( boost::outbuf::underlying_outbuf<1>& destination
                  , const char32_t* src
                  , std::size_t src_size );

Now the caller can pass any basic_outbuf<CharT>, as long as sizeof(CharT) is 1:

const char32_t* src             = /*...*/;
std::size_t src_size            = /*...*/;
boost::basic_outbuf<char>& dest = /*...*/;

utf32_to_utf8(dest.as_underlying(), src, src_size);

2. Reference

2.1. Header boost/outbuf.hpp

2.1.1. min_size_after_recycle

template <typename CharT>
constexpr std::size_t min_size_after_recycle();
Return value

Implementation-defined value greater than or equal to 64.

2.1.2. underlying_outbuf

Synopsis
namespace boost {

template <std::size_t CharSize>
class underlying_outbuf;
{
public:

    using char_type = /*see below*/;

    underlying_outbuf(const underlying_outbuf&) = delete;
    underlying_outbuf(underlying_outbuf&&) = delete;
    underlying_outbuf& operator=(const underlying_outbuf&) = delete;
    underlying_outbuf& operator=(underlying_outbuf&&) = delete;

    virtual ~underlying_outbuf() = default;

    char_type* pos() const noexcept;
    char_type* end() const noexcept;
    std::size_t size() const noexcept;
    bool good() const noexcept;
    void advance_to(char_type* p);
    void advance(std::size_t n);
    void require(std::size_t s);

    virtual bool recycle() = 0;

protected:

    underlying_outbuf(char_type* pos_, char_type* end_);

    underlying_outbuf(char_type* pos_, std::size_t n);

    void set_pos(char_type* p) noexcept;
    void set_end(char_type* e) noexcept;
    void set_good(true g) noexcept;
};

// global type aliases

template <std::size_t CharSize>
using underlying_outbuf_char_type = typename underlying_outbuf<CharSize>::char_type

// global functions

template <std::size_t CharSize>
void write( boost::underlying_outbuf<CharSize>& ob
          , const boost::underlying_outbuf_char_type<CharSize>* data
          , std::size_t data_size );

template <std::size_t CharSize>
void write( boost::underlying_outbuf<CharSize>& ob
          , const boost::underlying_outbuf_char_type<CharSize>* data
          , const boost::underlying_outbuf_char_type<CharSize>* data_end );

template <std::size_t CharSize>
void put( boost::underlying_outbuf<CharSize>& ob
        , boost::underlying_outbuf_char_type<CharSize> ch );

} // namespace boost
Member types
using char_type = /*see below*/;
Equal to
  • std::uint8_t if CharSize == 1

  • char16_t if CharSize == 2

  • char32_t if CharSize == 4

It is undefined for any other CharSize value.

Public member functions
char_type* pos() const noxcept;
Return

The memory position where the content shall be written.

char_type* end() const noxcept;
Return

The end of memory position where the content shall be written. Dereferencing end() has undefined behaviour.

std::size_t size() const noexcept;
Return

end() - pos()

virtual void recycle() = 0;
Posconditions
  • size() >= min_size_after_recycle<char_type>()

  • The range [ pos(), end() ) is valid accessible memory area

  • If the return value of good() was false before this call to recycle(), then good() remains returning false.

void require(std::size_t s)
Effect

Calls recycle() if size() < s.

Precondition

s <= min_size_after_recycle<char_type>()

Postcondition

size() >= s

void advance_to(char_type* p)
Effect

Advance the buffer’s position to p.

Precondition

pos() <= p && p <= end()

Postcondition

pos() == p

void advance(std::size_t n)
Effect

Same as advance_to(pos() + n)

Precondition

n <= size()

void advance()
Effect

Same as advance_to(1)

Precondition

pos() != end()

bool good() const;
Return

The state of this object. If the return value is false, then it means that calling advance of advance_to has no relevant side effect because the content written in the buffer will not be read anymore.

Note

The range [ pos(), end() ) shall aways be a valid accessible memory, even when good() returns false.

Protected Member functions
underlying_outbuf(CharT* pos_, CharT* end_)
Preconditions
  • pos_ <= end_

  • The range [ pos_, end_ ) must be an accessible memory area.

Posconditions
  • pos() == pos_

  • end() == end_

  • good() == true

underlying_outbuf(CharT* pos_, std::size_t n)
Preconditions
  • The range [ pos_, `pos_ + n ` ) must be an accessible memory area.

Posconditions
  • pos() == pos_

  • end() == pos_ + n

  • good() == true

void set_pos(CharT* p) noexcept
Postconditions

pos() == p

void set_end(CharT* e) noexcept
Postconditions

end() == e

void set_good(bool g) noexcept
Postconditions

good() == g

Global functions
template <std::size_t CharSize>
void put( boost::underlying_outbuf<CharSize>& ob
        , boost::underlying_outbuf_char_type<CharSize> ch );
Effect

Same as:

if (ob.size() == 0) {
    ob.recycle();
}
*ob.pos() = ch;
ob.advance();
template <std::size_t CharSize>
void write( boost::underlying_outbuf<CharSize>& ob
          , const boost::underlying_outbuf_char_type<CharSize>* data
          , const boost::underlying_outbuf_char_type<CharSize>* data_end );
Effect

Writes the the range [ data, data_end ) into ob, calling ob.recycle() how many times are necessary.

template <std::size_t CharSize>
void write( boost::underlying_outbuf<CharSize>& ob
          , const boost::underlying_outbuf_char_type<CharSize>* data
          , std::size_t data_size );
Effect

Same as write(ob, data, data + data_size)

2.1.3. basic_outbuf

Synopsis
namespace boost {

template <typename CharT>
class basic_outbuf: private underlying_outbuf<sizeof(CharT)>
{
public:
    using char_type = CharT;
    basic_outbuf(const basic_outbuf&) = delete;
    basic_outbuf(basic_outbuf&&) = delete;
    basic_outbuf& operator=(const basic_outbuf&) = delete;
    basic_outbuf& operator=(basic_outbuf&&) = delete;

    virtual ~basic_outbuf() = default;

    underlying_outbuf<sizeof(CharT)>& as_underlying() noexcept;
    const underlying_outbuf<sizeof(CharT)>& as_underlying() const noexcept;

    char_type* pos() const noexcept;
    char_type* end() const noexcept;
    void advance_to(char_type* p);

    using underlying_outbuf<sizeof(CharT)>::size;
    using underlying_outbuf<sizeof(CharT)>::advance;
    using underlying_outbuf<sizeof(CharT)>::good;
    using underlying_outbuf<sizeof(CharT)>::require;
    using underlying_outbuf<sizeof(CharT)>::recycle;

protected:

    basic_outbuf(char_type* pos_, char_type* end_);
    basic_outbuf(char_type* pos_, std::size_t n);

    void set_pos(char_type* p) noexcept;
    void set_end(char_type* e) noexcept;

    using underlying_outbuf<sizeof(CharT)>::set_good;
};

// global type aliases

using outbuf      = basic_outbuf<char>;
using u8outbuf    = basic_outbuf<char8_t>;
using u16outbuf   = basic_outbuf<char16_t>;
using u32outbuf   = basic_outbuf<char32_t>;
using woutbuf     = basic_outbuf<wchar_t>;
using bin_outbuf  = basic_outbuf<std::byte>;

// global functions

template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
          , const CharT* data
          , std::size_t count );

template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
          , const CharT* data
          , const CharT* data_end );

void write(boost::basic_outbuf<char>& ob, const char* cstr);

void write(boost::basic_outbuf<wchar_t>& ob, const wchar_t* cstr);

template <typename CharT>
void put(boost::basic_outbuf<CharT>& ob, CharT ch);

} // namespace boost
Public member functions
underlying_outbuf<sizeof(CharT)>& as_underlying() noexcept;
const underlying_outbuf<sizeof(CharT)>& as_underlying() const noexcept;
Return

*this

char_type* pos() const noexcept;
Return

(CharT*) as_underlying().pos();

char_type* end() const noexcept;
Return

(CharT*) as_underlying().end();

void advance_to(char_type* p);
Effect

Same as

as_underlying().advance_to((underlying_outbuf_char_type<sizeof(CharT)>*)p)
Precondition

p <= end()

Public member functions inherited from private base underlying_outbuf<sizeof(CharT)>
    using underlying_outbuf<sizeof(CharT)>::size;
    using underlying_outbuf<sizeof(CharT)>::advance;
    using underlying_outbuf<sizeof(CharT)>::good;
    using underlying_outbuf<sizeof(CharT)>::require;
    using underlying_outbuf<sizeof(CharT)>::recycle;
Protected member functions
basic_outbuf(char_type* pos_, char_type* end_);
Effect

Initializes private base class underlying_outbuf<sizeof(CharT)> with pos_ and end_ casted as underlying_outbuf_char_type<sizeof(CharT)>*.

basic_outbuf(char_type* pos_, std::size_t n);
Effect

Same as basic_outbuf(pos_, pos + n)

void set_pos(char_type* p) noexcept;
Effect

Same as

as_underlying().set_pos((underlying_outbuf_char_type<sizeof(CharT)>*)p)
void set_end(char_type* e) noexcept;
Effect

Same as

as_underlying().set_end((underlying_outbuf_char_type<sizeof(CharT)>*)e)
void set_good(bool g) noexcept;
Effect

Same as as_underlying().set_good(g)

Global functions
template <typename CharT>
void put(boost::basic_outbuf<CharT>& ob, CharT ch);
Effect

Same as:

if (ob.size() == 0) {
    ob.recycle();
}
*ob.pos() = ch;
ob.advance();
template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
          , const CharT* data
          , const CharT* data_end );
Effect

Writes the the range [ data, data_end ) into ob, calling ob.recycle() how many times are necessary.

template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
          , const CharT* data
          , std::size_t data_size );
Effect

Same as write(ob, data, data + data_size)

void write( boost::basic_outbuf<char>& ob
          , const char* cstr );
Effect

Same as write(ob, cstr, std::strlen(cstr))

void write( boost::basic_outbuf<wchar_t>& ob
          , const wchar_t* wcstr );
Effect

Same as write(ob, wcstr, std::wstrlen(wcstr))

2.1.4. basic_outbuf_noexcept

namespace boost {

template <typename CharT>
class basic_outbuf_noexcept: public basic_outbuf<CharT>
{
public:

    virtual void recycle() noexcept = 0;

protected:

    using basic_outbuf<CharT>::basic_outbuf;
};

// type aliases

using outbuf_noexcept      = basic_outbuf_noexcept<char>;
using u8outbuf_noexcept    = basic_outbuf_noexcept<char8_t>;
using u16outbuf_noexcept   = basic_outbuf_noexcept<char16_t>;
using u32outbuf_noexcept   = basic_outbuf_noexcept<char32_t>;
using woutbuf_noexcept     = basic_outbuf_noexcept<wchar_t>;
using bin_outbuf_noexcept  = basic_outbuf_noexcept<std::byte>;

} // namespace boost

2.1.5. Garbage buffer

These function templates return the begin and the end of a memory area that is never supposed to be read. It can be used when implementing a class that derives from basic_outbuf to set the buffer when the state is "bad".

template <typename CharT>
CharT* outbuf_garbage_buf();
template <typename CharT>
CharT* outbuf_garbage_buf_end();

2.1.6. basic_cstr_writer

namespace boost {

template <typename CharT>
class basic_cstr_writer final: public boost::basic_outbuf_noexcept<CharT>
{
public:

    basic_cstr_writer(CharT* dest, CharT* dest_end);
    basic_cstr_writer(CharT* dest, std::size_t len);
    template <std::size_t N>
    basic_cstr_writer(CharT (&dest)[N]);

    void recycle() noexcept override;
    struct result
    {
        CharT* ptr;
        bool truncated;
    };
    result finish();
};
Public member function
basic_cstr_writer(CharT* dest, CharT* dest_end);
Precondition

dest < dest_end

Postconditions
  • good() == true

  • pos() == dest

  • end() == dest_end - 1

basic_cstr_writer(CharT* dest, std::size_t dest_size);
Precondition

dest_size != 0

Postconditions
  • good() == true

  • pos() == dest

  • end() == dest + dest_size - 1

template <std::size_t N>
basic_cstr_writer(CharT (&dest)[N]);
Postconditions
  • good() == true

  • pos() == dest

  • end() == dest + N - 1

void recycle() noexcept;
Postconditions
  • good() == false

  • pos() == outbuf_garbage_buf<CharT>()

  • end() == outbuf_garbage_buf_end<CharT>()

result finish();
Effects
  • Assign to '\0' the position after the last written character in memory area used to initialize this object and set this object into "bad" state.

Return value
  • result::truncated is true if recycle or finish has ever been called in this object.

  • retulr::ptr is the position after the last written character in memory area used to initialize this object

Postconditions
  • good() == false

  • pos() == outbuf_garbage_buf<CharT>()

  • end() == outbuf_garbage_buf_end<CharT>()

2.1.7. discarded_outbuf

namespace boost {

template <typename CharT>
class discarded_outbuf final: public basic_outbuf_noexcept<CharT>
{
public:
    discarded_outbuf();
    ~discarded_outbuf() = default;
    void recycle() noexcept override
};

} // namespace boost
Public member functions
discarded_outbuf();
Posconditions
  • good() == false

  • pos() == outbuf_garbage_buf<CharT>()

  • end() == outbuf_garbage_buf_end<CharT>()

void recycle() noexcept;
Posconditions
  • good() == false

  • pos() == outbuf_garbage_buf<CharT>()

  • end() == outbuf_garbage_buf_end<CharT>()

2.2. Header boost/outbuf/iterator.hpp

2.2.1. underlying_outbuf_iterator

Synopsis
template <std::size_t CharSize>
class underlying_outbuf_iterator
{
public:

    using char_type = underlying_outbuf_char_type<CharSize>;
    using value_type = void;
    using difference_type = void;
    using pointer = void;
    using reference = void;
    using iterator_category = std::output_iterator_tag;

    explicit underlying_outbuf_iterator(underlying_outbuf<CharSize>&) noexcept;
    underlying_outbuf_iterator(const underlying_outbuf_iterator<CharSize>&) noexcept;

    underlying_outbuf_iterator& operator*() noexcept; // no-op
    underlying_outbuf_iterator& operator++() noexcept; // no-op
    underlying_outbuf_iterator& operator++(int) noexcept; // no-op
    underlying_outbuf_iterator& operator=(char_type ch);
    underlying_outbuf_iterator& operator=(const underlying_outbuf_iterator&) noexcept;
};
Public member functions
explicit underlying_outbuf_iterator(underlying_outbuf<CharSize>& ob) noexcept;
Effect

Initializes the private underlying_outbuf<CharSize>& with ob

underlying_outbuf_iterator& operator*() noexcept;
underlying_outbuf_iterator& operator++() noexcept;
underlying_outbuf_iterator& operator++(int) noexcept;
Effect

Returns *this;

underlying_outbuf_iterator& operator=(char_type ch);
Return

*this

Effect

same as put(ob, ch), where ob is the reference used to initialize this object.

2.2.2. outbuf_iterator

Synopsis
template <typename CharT>
class outbuf_iterator
{
public:

    using char_type = CharT
    using value_type = void;
    using difference_type = void;
    using pointer = void;
    using reference = void;
    using iterator_category = std::output_iterator_tag;

    explicit outbuf_iterator(basic_outbuf<CharT>&) noexcept;
    outbuf_iterator(const basic_outbuf<CharT>&) noexcept;

    outbuf_iterator& operator*() noexcept; // no-op
    outbuf_iterator& operator++() noexcept; // no-op
    outbuf_iterator& operator++(int) noexcept; // no-op
    outbuf_iterator& operator=(char_type ch);
    outbuf_iterator& operator=(const outbuf_iterator&) noexcept;
};
Public member functions
explicit outbuf_iterator(basic_outbuf<CharT>& ob) noexcept;
Effect

Initializes the private basic_outbuf<CharT>& with ob

outbuf_iterator& operator*() noexcept;
outbuf_iterator& operator++() noexcept;
outbuf_iterator& operator++(int) noexcept;
Effect

Returns *this;

outbuf_iterator& operator=(char_type ch);
Return

*this

Effect

same as put(ob, ch), where ob is the reference used to initialize this object.

2.3. Header boost/outbuf/string.hpp

2.3.1. basic_string_maker

Synopsis
namespace boost {

template < typename CharT
         , typename Traits = std::char_traits<CharT>
         , typename Allocator = std::allocator<CharT> >
class basic_string_maker final: public basic_outbuf<CharT>
{
public:
    basic_string_maker();
    void reserve(std::size_t size);
    void recycle() override;
    basic_string<CharT, Traits, Allocator> finish();
};

// Global type aliases

using string_maker    = basic_string_maker<char>;
using u16string_maker = basic_string_maker<char16_t>;
using u32string_maker = basic_string_maker<char32_t>;
using wstring_maker   = basic_string_maker<wchar_t>;
using u8string_maker  = basic_string_maker<char8_t>;

} // namespace boost
Public member functions
void reserve(std::size_t size);
Effect

Calls str.reserve(size), where str is the private string object that is returned by finish().

void recycle() override;
Effects
  • If good() is true then calls str.append(p0, pos()), where str is the private string object that is returned by finish(), and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle() ( all in this object ), or since this object’s contruction, whatever happened last.

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

basic_string<CharT, Traits, Allocator> finish()
Effects

Calls recycle() and set_good(false) and return the internal string.

Postconditions

good() == false

2.3.2. basic_string_maker_noexcept

Synopsis
namespace boost {

template < typename CharT
         , typename Traits = std::char_traits<CharT>
         , typename Allocator = std::allocator<CharT> >
class basic_string_maker_noexcept final: public basic_outbuf_noexcept<CharT>
{
public:
    basic_string_maker_noexcept();
    void reserve(std::size_t size);
    void recycle() noexcept override;
    basic_string<CharT, Traits, Allocator> finish();
};

// Global type aliases

using string_maker_noexcept    = basic_string_maker_noexcept<char>;
using u16string_maker_noexcept = basic_string_maker_noexcept<char16_t>;
using u32string_maker_noexcept = basic_string_maker_noexcept<char32_t>;
using wstring_maker_noexcept   = basic_string_maker_noexcept<wchar_t>;
using u8string_maker_noexcept  = basic_string_maker_noexcept<char8_t>;

} // namespace boost
Public member functions
void reserve(std::size_t size);
Effect

Calls str.reserve(size), where str is the private string object that is returned by finish().

void recycle() override;
Effects
  • If good() is true then calls str.append(p0, pos()), where str is the private string object that is returned by finish(), and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle(), or since this object’s contruction, whatever happened last.

  • If an exception is thrown, hold it with a std::exception_ptr and calls set_good(false).

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

basic_string<CharT, Traits, Allocator> finish()
Effects
  • Calls recycle() and set_good(false).

  • Calls std::rethrow_exception(eptr) if eptr is not null, where eptr is the internal std::exception_ptr that stores the exception thrown during recycle().

Postconditions

good() == false

2.3.3. basic_string_appender

Synopsis
namespace boost {

template < typename CharT
         , typename Traits = std::char_traits<CharT>
         , typename Allocator = std::allocator<CharT> >
class basic_string_appender final: public basic_outbuf<CharT>
{
public:
    explicit basic_string_appender(basic_string<CharT, Traits, Allocator>& dest);
    void reserve(std::size_t size);
    void recycle() override;
    void finish();
};

// Global type aliases

using string_appender    = basic_string_appender<char>;
using u16string_appender = basic_string_appender<char16_t>;
using u32string_appender = basic_string_appender<char32_t>;
using wstring_appender   = basic_string_appender<wchar_t>;

} // namespace boost
Public member functions
void reserve(std::size_t size);
Effect

Calls str.reserve(str.size() + size), where str is the reference that this object was initialized with.

void recycle() override;
Effects
  • If good() is true then calls str.append(p0, pos()), where str is the reference that this object was initialized with, and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle() ( all in this object ), or since this object’s contruction, whatever happened last.

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

void finish()
Effects

Calls recycle() and set_good(false).

Postcondition

good() == false

2.3.4. basic_string_appender_noexcept

Synopsis
namespace boost {

template < typename CharT
         , typename Traits = std::char_traits<CharT>
         , typename Allocator = std::allocator<CharT> >
class basic_string_appender_noexcept final: public basic_outbuf_noexcept<CharT>
{
public:
    explicit basic_string_appender_noexcept(basic_string<CharT, Traits, Allocator>& dest);
    void reserve(std::size_t size);
    void recycle() override;
    void finish();
};

// Global type aliases

using string_appender_noexcept    = basic_string_appender_noexcept<char>;
using u16string_appender_noexcept = basic_string_appender_noexcept<char16_t>;
using u32string_appender_noexcept = basic_string_appender_noexcept<char32_t>;
using wstring_appender_noexcept   = basic_string_appender_noexcept<wchar_t>;

} // namespace boost
Public member functions
void reserve(std::size_t size);
Effect

Calls str.reserve(str.size() + size), where str is the reference that this object was initialized with.

Effects
  • If good() is true then calls str.append(p0, pos()), where str is the reference this object was initialized with, and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle(), or since this object’s contruction, whatever happened last.

  • If an exception is thrown, hold it with a std::exception_ptr and calls set_good(false).

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

void finish()
Effects
  • Calls recycle() and set_good(false).

  • Calls std::rethrow_exception(eptr) if eptr is not null, where eptr is the internal std::exception_ptr that stores the exception thrown during recycle().

Postconditions

good() == false

2.4. Header boost/outbuf/streambuf.hpp

2.4.1. basic_streambuf_writer

Synopsis
namespace boost {

template <typename CharT, typename Traits = std::char_traits<CharT> >
class basic_streambuf_writer final: public boost::basic_outbuf<CharT>
{
public:
    explicit basic_streambuf_writer(std::basic_streambuf<CharT, Traits>& dest);
    void recycle() override;
    struct result
    {
        std::streamsize count;
        bool success;
    };
    result finish();
};

// Global type aliases

using streambuf_writer
    = basic_streambuf_writer<char, std::char_traits<char> >;

using wstreambuf_writer
    = basic_streambuf_writer<wchar_t, std::char_traits<wchar_t> >;

} // namespace boost
Public member functions
void recycle() override;
Effects
  • If good() is true then calls dest.sputn(p0, pos() - p0), where dest is the reference this object was initialized with, and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle(), or since this object’s contruction, whatever happened last.

  • If the returned value of dest.sputn is less then pos() - p0, calls set_good(false).

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

result finish();
Effects
  • Calls recycle() and set_good(false).

Return value
  • result::count is the sum of the values returned by dest.sputn.

  • result::success is the value good() would return before this call to finish().

2.5. Header boost/outbuf/cfile.hpp

2.5.1. narrow_cfile_writer

Synopsis
namespace boost {

template <typename CharT>
class narrow_cfile_writer final: public boost::basic_outbuf_noexcept<CharT>
{
public:
    explicit narrow_cfile_writer(std::FILE* dest);
    void recycle() noexcept;
    struct result
    {
        std::size_t count;
        bool success;
    };
    result finish();
};
} // namespace boost
Public member functions
void recycle() override;
Effects
  • If good() == true, calls std::fwrite(p0, pos() - p0, sizeof(CharT), dest), where dest is the FILE* used to initialize this object, and p0 is return value of pos() before any call to advance and advance_to since the last call to recycle(), or since this object’s contruction, whatever happened last.

  • If the returned value of std::fwrite is less then pos() - p0, calls set_good(false).

  • Calls set_pos and/or set_end.

Postconditions

size() >= min_size_after_recycle<CharT>()

Effects
  • Calls recycle() and set_good(false).

Return value
  • result::count is the sum of values returned by all calls std::fwrite done by this object.

  • result::success is the value good() would return before this call to finish()

2.5.2. wide_cfile_writer

Synopsis
namespace boost {

template <typename CharT>
class wide_cfile_writer final: public boost::basic_outbuf_noexcept<CharT>
{
public:
    explicit wide_cfile_writer(std::FILE* dest);
    void recycle() noexcept;
    struct result
    {
        std::size_t count;
        bool success;
    };
    result finish();
};
} // namespace boost
Public member functions
void recycle() override;
Effects
  • If good() == true, for each character ch in the range [ p0, pos() ) calls std::fputwc(ch, dest), until WEOF is returned or the whole range is read, where dest is the FILE* used to initialize this object, and p0 is the return value of pos() before any call to advance and advance_to since the last call to recycle(), or since this object’s contruction, whatever happened last.

  • If std::fputwc returns WEOF, calls set_good(false).

  • Calls set_pos and/or set_end.

result finish();
Effects
  • Calls recycle() and set_good(false).

Return value
  • result::count is the number of calls to std::fputwc by this object that did not return WEOF .

  • result::success is the value good() would return before this call to finish()