by: Reece H Dunn

I/O Formatting Manipulators

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();
};
 
attribute/method description
open_default The default for the open list parameter.
close_default The default for the close list parameter.
separator_default The default for the separator parameter.
isok Checks to see if the FormatType value is ok to be rendered.
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())
but is shorter to write.
 
[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 > & const 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 );
[Note: This example makes use of variables defined in earlier examples. ]]
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 > & const 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 );
[Note: This example makes use of variables defined in earlier examples. ]]
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]
4.5. boost::io::container_output
 
[todo]
4.6. boost::io::array_output
 
[todo]
5

Portability
 
The code has been succesfully tested on:
  1. MSVC 7.0;
  2. Borland C++Compiler 5.5.1;
  3. GNU G++ 3.0.3 (under the i686-pc-cygwin environment)
in the Win32 environment on a Windows XP/Pentium II machine.
 
The code does not work on the following:
  1. GNU G++ 2.95.3-5 (under the i686-pc-cygwin environment).
 
[Note: I do not have the facilities to test it on other machines/compilers. ]
5.1. const T & const
 
I have had a few problems porting this construct over to various compilers:
[1]
GCC 3.0.3: The GCC compiler produces a "discarding 'const' applied to a reference" message, and does not want to produce a *.o file.
[2]
MSVC 7.0: The Microsoft compiler produces a warning, saying: "anacronism
[3]
BC++Compiler 5.5.1: The Borland compiles the code without any errors or warnings.
6

Future Directions
 
[todo]
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:
Paul A. Bristow:
for his comments and suggestions;