From: Vladimir Prus (ghost_at_[hidden])
Date: 2004-09-23 00:55:23
> I see the library as the inverse of Spirit. Spirit takes a linear text
> builds complex objects, while the output formatting library takes complex
> objects and renders them as linear text.
Interesting! Hartmut Kaiser has expressed the similar view (off-list).
> II. A system for allowing user-defined type to advertise their internal
> structure, so that they can be accessed like the types in I. For example,
> a Dog class might advertise that it consists of a string name and a float
> weight. There are a number of ways that this could be done, such as with
> members-pointers, default-constuctible functors which extract the
> information, etc. Any combination of these techniques should be allowed.
Isn't this close to using 'serialize' for extracting members, that I
> III A framework of composable formatting objects (I'm using the term
> differently than the current library does) used to customize how complex
> types are output.
> A. The main building block is the concept of a Formatter (sketched
> There will be a number of built-in formatters, such as
> 1. sequence_formatter, for formatting objects of a type I.A.1.
> specified opening, closing and separator strings
> 2. nary_formatter<N>, for formatting objects of a type I.A.2. Nary
> formatters can be specified with expression templates -- e.g.,
> str("[") << _2 << " : " << _1 << ")"
> would format a pair (a, b) as [b : a). (Note the reversed order.)
Wow, that's nice coincidence, here's a part of email I've sent to Hartmut
should accept two parameters?
list_(';', str("(") << _1 << "," << _2)[phoenix::val(v)]
There's still a question where do you specify the stream... but basically,
the model that each formatter is just a functional object is a very simple
one, and that's good.
> also expeirmented with the following notation, for formatting user-defined
> str("Dog:") << member(dog_name)
> << ","
> << member(dog_height)
> << "]"
I'd still prefer 'serialize', just so that we have one method of describing
> C. A single function boost::io::format, which takes an arbitrary type
> returns an object which can be output using operator<<. Examples:
> cout << boost::io::format(obj); // Uses the default style
> cout << boost::io::format(obj).with(dog_format()) // Doggy-style
> cout << boost::io::format(obj) // Uses a complex style
> .use< is_vector<_> >( sequence_format("[", ",", "]")
> .use< is_pair<_> >( str("(") << _1 << ":" << _2 << "]"
Oh, MPL lambda? That's a cool idea! But isn't this a bit too flexible? At
all events, the smaller the size of the headers I need to include, the
> Finally, let me describe what a formatter looks like. It is a class type
> with a templated member function format having the following signature
> template<typename Ch, typename Tr, typename T, typename Context>
> basic_ostream<Ch, Tr>&
> format(basic_ostream<Ch, Tr>& out, const T& t, Context& ctx);
> Here T is the type whose instance is to be formatted, and ctx contains the
> prevailing Style (a combination of formatters)
If 'format' is a member of formatter, then why context should store some
other formatter? Or are they formatters for nested types?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk