Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2003-04-25 15:22:55


>From: "Paul A. Bristow" <boost_at_[hidden]>

> This looks interesting, but overlaps with recent work by Reece Dunn and
Terje
> Slettebo, so you should catch up on their work first?
>
> There is certainly a crying need for an easy to use formatted STL and C++
> containers output, but how _BEST_ to do this is not yet clear. Much wheel
> reinvention has already taken place: I hope Boosters can provide some
smart
> alloys at a good price ;-)

In the following, I compare the approaches a little (between my library and
John's; I'll let Reece speak for his. :) ). I've read John's two articles,
given earlier in the thread.

My library (http://article.gmane.org/gmane.comp.lib.boost.devel/18441) takes
the approach of being very easy to output composite types (arrays,
containers, std::pair, etc.), by overloading operator<< for them, in
appropriate headers. This means you can output them like any type with
stream operators defined.

It also makes it possibly generic, as you can output any object the same
way, without specifying what type it is.

This also means that there's no formatting/transformation object supplied,
in the output statement. This therefore has to be specified in some other
way. The library uses manipulators, which stores the formatting information
for each type using xalloc().

Currently, all formatting objects are the same type, to be able to
store/retrieve them from the stream, for formatting. This means that custom
formatters/transformers aren't available.

It would be possible to add custom formatters/transformers, if another
approach was taken to storing it, such as all formatters/transformers
deriving from a common interface, using virtual functions, and dynamical
allocation of the formatters/transformers. Because of this change, that has
not been done, so far.

John's library (given in the articles) uses explicit specification of the
output, using functions (container(), range(), coll_container()), which may
be supplied with formatting/transforming objects. Since these objects are
given at the invocation, they may be statically bound, and hence, custom
formatters/transformers can be used.

They say a picture is worth a thousand words (or vice versa. :) ), so let's
look at some examples of output, using the two, as I understand the library,
from the article. John or anybody, feel free to provide additional examples.

Examples from John's article:

The output of the following is:

1 - John, James, Corina

2 - {John}, {James}, {Corina}

3 -
[John]
[James]
[Corina]

4 - {[0] John}, {[1] James}, {[2] Corina}

If the names are stored in a container:

Library A:

std::cout << container(names);
std::cout << container(names, formatter( "{", "}, {", "}"));
std::cout << container(names, formatter( "[", "]\n[", "]"));
std::cout << container(names, formatter( PrefixByIndex(), "{", "}, {","}"));

Library B:

std::cout << names;
std::cout << format<container_type>("{", "}", "}, {") << names;
std::cout << format<container_type>("[", "]", "]\n[") << names;
Not available - requires custom formatter

If the names are stored in an array (only default or earlier set formatting
shown. Formatting can be specified as above):

A:

std::cout << range(names);

B:

std::cout << names;

To output only a range (any sequence):

A:

std::cout << range(names, names+10);

B:

std::cout << sequence<sequence_type>(names, names+10);

I've also considered "range" for this function, and it's another
possibility. :)

If the names are stored in associative containers:

1 - Default formatting
2 - Using custom formatting:

A -> 1
B -> 2
C -> 3

A:

std::cout << coll_container(names);
std::cout << coll_container( collWords,
    formatter( coll_transform( "%k -> %v"), "\n"));

B:

std::cout << names;
std::cout << format<element_type>("", "\n", " -> ")
          << format<map>("", "", "")
          << names;

Regards,

Terje


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk