I/O Formatting Manipulators | |||
| |||
1. | ||||||||||||||||||||
1.1. | ||||||||||||||||||||
1.2. | ||||||||||||||||||||
2. | ||||||||||||||||||||
2.1. | ||||||||||||||||||||
2.2. | ||||||||||||||||||||
2.3. | ||||||||||||||||||||
2.3.1. | ||||||||||||||||||||
2.3.2. | ||||||||||||||||||||
2.3.3. | ||||||||||||||||||||
2.3.4. | ||||||||||||||||||||
2.4. | ||||||||||||||||||||
3. | ||||||||||||||||||||
3.1. | ||||||||||||||||||||
3.2. | ||||||||||||||||||||
3.3. | ||||||||||||||||||||
3.4. | ||||||||||||||||||||
3.5. | ||||||||||||||||||||
4. | ||||||||||||||||||||
4.1. | ||||||||||||||||||||
4.2. | ||||||||||||||||||||
4.3. | ||||||||||||||||||||
4.4. | ||||||||||||||||||||
4.5. | ||||||||||||||||||||
4.6. | ||||||||||||||||||||
5. | ||||||||||||||||||||
6. | ||||||||||||||||||||
6.1. | ||||||||||||||||||||
6.2. | ||||||||||||||||||||
7. | ||||||||||||||||||||
|
1 |
Introduction |
1.1. The Problem |
The C++ Input/Output library provides a mechanism for customizing the
way a class is represented on a linear text stream. There are output
operations for the basic data types as well as for std::complex and other data types in
the standard library. |
Having said that, there are no output operations for any of the STL
container types. There is a reason for this: how do we represent the list?
Different applications would want different ways for the list to be
represented, so there is no easy way to specify a default format. What if
you need to output a sub-list? Or have the same format across different
container types? Or have different formatting for different objects that
have the same container type? |
1.2. The Solution |
Designing a library that can cope with these problems, as well as
others not considered here, while remaining efficient is no easy task.
There are other attempts to solve these sorts of problems. |
The motivation behind using manipulators is that they are already
designed into the C++ I/O library and require little overhead in the
output process. They also give the user maximum choice in how the data being outputted is
formatted. |
2 |
Formatter Objects |
2.1. Overview |
The formatter object forms the basis for all formatting configuration
within this library. |
[Example:
boost::io::formatter< char > fmt;
fmt.format( '(' , ')' ); |
[Example:
boost::io::formatter< char * > fmt2;
fmt2.format( "--" ).space( true, true
); |
2.2. boost::io::format_traits |
The format_traits class
provides the default values for the format constants in a formatter
object. It has the following form: |
template<> class boost::io::format_traits< FormatType >
{
public:
static FormatType open_default;
static FormatType close_default;
static FormatType
separator_default; public:
static inline bool isok( FormatType )
throw(); }; |
|
[Note: This class is part of
the implementation details, and should only be extended to support format
types not provided for here, such as std::basic_string types. ] |
2.3. boost::io::formatter_t |
[todo] |
2.3.1. Formatting Options |
[todo] |
2.3.2. Spacing Options |
[todo] |
2.3.3. Configuration From Another Formatter
Object |
[todo] |
2.3.4. Constructors |
[todo] |
2.4. boost::io::formatter |
[todo] |
3 |
The Manipulators |
3.1. Overview |
The list formatting manipulators provide the mechanism for rendering
lists to an output stream. |
3.2. boost::io::formatlist_t |
[todo] |
3.3. boost::io::formatlist |
These are the basic forms of the formatlist manipulator. |
template< typename ForwardIterator >
inline boost::io::formatlist_t< ForwardIterator > boost::io::formatlist
(
ForwardIterator first,
ForwardIterator last ); |
This specifies a list from first to last that is to be rendered to the
output stream. |
[Example:
int i[ 4
] = { 3, 6,
9, 12 };
std::cout << boost::io::formatlist( i, i + 4 ); |
template< class Container >
inline boost::io::formatlist_t< typename Container::iterator > boost::io::formatlist
(
Container & c ); |
This specifies a container to be rendered to the output stream, and
is equivalent to
boost::io::formatlist( c.begin(),
c.end()) |
[Example:
std::vector< int > v( 10
);
std::generate( v.begin(), v.end(), std::rand );
std::cout << boost::io::formatlist( v ); |
The following forms of the list format manipulator accept a formatter
object to specify how the list is rendered. |
[Note: These manipulator forms
will inherit the format type from the formatter object, and thus it does
not need to be explicitly specified. ] |
template< typename ForwardIterator, typename FormatType, class RefType >
inline boost::io::formatlist_t< ForwardIterator,
FormatType > boost::io::formatlist
(
ForwardIterator first,
ForwardIterator last,
const boost::io::formatter_t< FormatType, RefType >
& fmt ); |
This specifies a list from first to last that is to be rendered to the
output stream using the formatting specified in fmt as its default values. |
[Example:
std::cout << boost::io::formatlist( i, i + 4, fmt );
std::cout << boost::io::formatlist( i, i + 4, fmt2 ); |
template< class Container, typename FormatType, class RefType >
inline boost::io::formatlist_t< typename Container::iterator, FormatType >
boost::io::formatlist
(
Container & c,
const boost::io::formatter_t< FormatType, RefType >
& fmt ); |
This specifies a container that is to be rendered to the output
stream using the formatting specified in fmt as its default values. |
[Example:
std::cout << boost::io::formatlist( v, fmt );
std::cout << boost::io::formatlist( v, fmt2
); |
3.4. boost::io::formatlistex |
These variants on the basic list format manipulator are to allow wide
character and string types to be used. |
template< typename FormatType, typename ForwardIterator >
inline boost::io::formatlist_t< ForwardIterator,
FormatList > boost::io::formatlistex
(
ForwardIterator first,
ForwardIterator last ); |
This specifies FormatType
and should be used if you need string or wide-character types. This is the
list range version. |
[Example:
char * str = "Hello World!" ;
std::cout << boost::io::formatlistex< char * >( str, str + std::strlen( str )).format( "==>" , "<=="
); |
template< typename FormatType, class Container >
inline boost::io::formatlist_t< typename Container::iterator, FormatList >
boost::io::formatlistex
(
Container & c ); |
This specifies FormatType
and should be used if you need string or wide-character types. This is the
container version. |
[Example:
std::list< char > l;
l.push_back( 'A' );
l.push_back( 'B' );
l.push_back( 'C' );
std::cout << boost::io::formatlistex< char * >( l ).format( "==" ).space( true,
true ); |
3.5. boost::io::formatlistfn |
These variants on the basic list format manipulator allow the user to
specify the way each item in the list is rendered. For a more detailed
description of what outputters are, see the relevant section. |
For examples of these manipulators, see the outputter section.
|
[Note: These manipulator forms
will inherit the format type from the outputter object, and thus it does
not need to be explicitly specified. ] |
template< typename ForwardIterator, typename Outputter >
inline boost::io::formatlist_t< ForwardIterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
ForwardIterator first,
ForwardIterator last,
Outputter out ); |
This is the sub-list variant. |
template< class Container, typename Outputter >
inline boost::io::formatlist_t< typename Container::iterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
Container c,
Outputter out ); |
This is the STL container variant. |
4 |
Outputters |
4.1. Outputter Function Objects |
[todo] |
4.2. boost::io::basic_output |
[todo] |
4.3. boost::io::stdpair_output |
[todo] |
4.4.
boost::io::detail::list_output |
[todo] |
[Note: This class is part of
the implementation details. It encapsulates the list rendering
functionality used by boost::io::formatlist_t, boost::io::array_output and boost::io::container_output. You
should use one of those classes if you want list rendering functionality.
] |
4.5. boost::io::container_output |
[todo] |
4.6. boost::io::array_output |
[todo] |
5 |
Portability |
The code has been succesfully tested on:
|
The code does not work on the following:
|
[Note: I do not have the
facilities to test it on other machines/compilers. ] |
6 |
Future Directions |
6.1. Position/Context Information |
Adding support for position information within a list. This would
allow more advanced formatting, like numbering each item or providing
special formatting for brace elements (i.e. the middle extension glyph).
|
I am currently thinking of supporting this as an extra (optional)
parameter to the function operator of the output functor. This parameter
will be a context-information object from the parent outputter that gives
information such as the length of the sub-list being outputted and the
current position within that sub-list. Other information may be added at a
future date. |
6.2. boost::io::stdpair_output
manipulators |
Add support for being able to output std::pair and std::complex
objects that are the root object and are not contained within lists.
|
7 |
Acknowledgements |
This library was designed and implemented by Reece H. Dunn. |
The output functors were based on a comment in the "IO for STL
containers" thread on the boost developers mailing list. |
Special thanks to:
|