|
Boost : |
From: Jason House (jhouse_at_[hidden])
Date: 2003-02-06 09:38:27
Terje Slettebø wrote:
> >From: "Jason House" <jhouse_at_[hidden]>
> > I thought of one thing that might work reasonably well.
> >
> > How about making ++io_format< T > save the current format in a stack.
> > and having io_format< T>-- restore the previously queuued format
>
> I've thought of the exact same thing. :) Not how the syntax for it would be,
> but when I was thinking of this, it suddenly occurred to me: State savers!
>
> This essentially creates a scope in the state space. As you say, you may
> then read the currently set format, and restore it afterwards. The
> restoration is important, and there are issues such as exception safety.
>
> > so, then something like
> >
> > > > std::cout << ++io_format<char (&)[3]>("\n|","|\n","|")--
> > > > << ++io_format<char
> (&)[3][3]>("-------","-------","-------")--
> > > > << board << '\n';
> >
> > would save and restore the formating for char(&)[3][3] and char(&)[3] and
> never
> > stomp on anything else.
>
> In this case, it seems it saves and restores the format, before the format
> gets a chance to be used. In other words, the scope only covers the state
> saving, not the output.
The idea was pre-increment and post-decrement... I wasn't sure if pre & post
operators work the same for classes as they do for primitive types.
> Another possibility might be to have a sentry object, doing automatic state
> saving and restoring in the constructor and destructor. In fact, there are
> already such classes in Boost: Daryle Walker's I/O state savers, which fits
> this situation like a glove.
>
> In your original posting, you had this example:
>
> >For instance, if you have a type
> >map<custom_object, list<string> >
>
> >and custom_object's stream output uses io_format<list<string> >, then
> >you are going to run into trouble if it wants a different formatting.
>
> Such a custom object may then have something like the following in its
> stream output:
>
> boost::io::ios_pword_saver(stream,index);
>
> // Set stream state, and do output.
>
> That's all. :)
>
> This also ensures that the state is restored properly, even in the presence
> of exceptions, something the ++/-- way won't do. Of course, this requires
> the pword-index, so one might make the interface more user friendly, and fit
> the rest, for example by making the state saver a manipulator, itself.
>
> As I understand, the lifetime of a temporary object extends until the end of
> the full expression it's used in, so the following should be well-defined:
>
> std::vector<int> v;
>
> std::cout << composite_save<vector<int> >() << composite_format(...) << v <<
> '\n';
>
> This saves the format at the start, and restores it at the end.
>
> An alternative is a named temporary, such as:
>
> composite_save<vector<int> > sentry(stream);
>
> // Set format and do output
I think that I like your solution better :) putting it constructor/deconstructor
does seem better. I can't even argue that it's more typing for multi-line
expressions...
When I originally started this, I said that it was the same complaint I have about
io_manip... It would be neat to have a replacement/wrapper boot library for
io_manip.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk