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
,
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.min_size_after_recycle
<char_type>()
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 |
|
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 |
std::size_t size() const noexcept;
Return |
|
virtual void recycle() = 0;
Posconditions |
|
void require(std::size_t s)
Effect |
Calls |
Precondition |
|
Postcondition |
|
void advance_to(char_type* p)
Effect |
Advance the buffer’s position to |
Precondition |
|
Postcondition |
|
void advance(std::size_t n)
Effect |
Same as |
Precondition |
|
void advance()
Effect |
Same as |
Precondition |
|
bool good() const;
Return |
The state of this object. If the return value is |
Note |
The range [ |
Protected Member functions
underlying_outbuf(CharT* pos_, CharT* end_)
Preconditions |
|
Posconditions |
|
underlying_outbuf(CharT* pos_, std::size_t n)
Preconditions |
|
Posconditions |
|
void set_pos(CharT* p) noexcept
Postconditions |
|
void set_end(CharT* e) noexcept
Postconditions |
|
void set_good(bool g) noexcept
Postconditions |
|
Global functions
template <std::size_t CharSize>
void put( boost::underlying_outbuf<CharSize>& ob
, boost::underlying_outbuf_char_type<CharSize> ch );
Effect |
Same as:
|
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 [ |
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 |
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 |
|
char_type* pos() const noexcept;
Return |
|
char_type* end() const noexcept;
Return |
|
void advance_to(char_type* p);
Effect |
Same as
|
Precondition |
|
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 |
basic_outbuf(char_type* pos_, std::size_t n);
Effect |
Same as |
void set_pos(char_type* p) noexcept;
Effect |
Same as
|
void set_end(char_type* e) noexcept;
Effect |
Same as
|
void set_good(bool g) noexcept;
Effect |
Same as |
Global functions
template <typename CharT>
void put(boost::basic_outbuf<CharT>& ob, CharT ch);
Effect |
Same as:
|
template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
, const CharT* data
, const CharT* data_end );
Effect |
Writes the the range [ |
template <typename CharT>
void write( boost::basic_outbuf<CharT>& ob
, const CharT* data
, std::size_t data_size );
Effect |
Same as |
void write( boost::basic_outbuf<char>& ob
, const char* cstr );
Effect |
Same as |
void write( boost::basic_outbuf<wchar_t>& ob
, const wchar_t* wcstr );
Effect |
Same as |
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 |
|
Postconditions |
|
basic_cstr_writer(CharT* dest, std::size_t dest_size);
Precondition |
|
Postconditions |
|
template <std::size_t N>
basic_cstr_writer(CharT (&dest)[N]);
Postconditions |
|
void recycle() noexcept;
Postconditions |
|
result finish();
Effects |
|
Return value |
|
Postconditions |
|
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 |
|
void recycle() noexcept;
Posconditions |
|
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_iterator& operator*() noexcept;
underlying_outbuf_iterator& operator++() noexcept;
underlying_outbuf_iterator& operator++(int) noexcept;
Effect |
Returns |
underlying_outbuf_iterator& operator=(char_type ch);
Return |
|
Effect |
same as |
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 |
outbuf_iterator& operator*() noexcept;
outbuf_iterator& operator++() noexcept;
outbuf_iterator& operator++(int) noexcept;
Effect |
Returns |
outbuf_iterator& operator=(char_type ch);
Return |
|
Effect |
same as |
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 |
void recycle() override;
Effects |
|
Postconditions |
|
basic_string<CharT, Traits, Allocator> finish()
Effects |
Calls |
Postconditions |
|
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 |
void recycle() override;
Effects |
|
Postconditions |
|
basic_string<CharT, Traits, Allocator> finish()
Effects |
|
Postconditions |
|
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 |
void recycle() override;
Effects |
|
Postconditions |
|
void finish()
Effects |
Calls |
Postcondition |
|
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 |
Effects |
|
Postconditions |
|
void finish()
Effects |
|
Postconditions |
|
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 |
|
Postconditions |
|
result finish();
Effects |
|
Return value |
|
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 |
|
Postconditions |
|
Effects |
|
Return value |
|
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 |
|
result finish();
Effects |
|
Return value |
|