formatting aggregates (Re: concrete example on "inheriting" from ostream)
Pete Becker ha scritto:
James Kanze wrote:
std::cout.imbue( "fr_FR" ) ;
std::cout << std::complex< double >( 1.2, 3.4 ) << std::endl ;
According to the standard, interpreted literally, this should
output:
(1,2,3,4)
Which is, of course, pattently ridiculous. (Supposing a normal
implementation of the locale "fr_FR" under Posix.) At the very
minimum, if the decimal point is a comma, the separator should
be a ';'; a better solution would be to introduce a list
separator character into numpunct facet.
That would take care of this particular problem, but there's a broader
issue with output of other aggregate types such as pair and tuple. And a
still broader one for containers such as vector. The original proposal
for tuple specified a stream inserter and a mechanism for setting the
begin and end delimiters and the separator. We dropped that because it,
too, didn't deal with the broader problems. Unfortunately, there's still
no work going on for that broader problems.
I've seen the original tuple proposal. I/O was based on
xalloc()/iword(), right? I understand why you decided to drop it.
So let's start brainstorming! :-)
The first thing that comes in my mind is adding a new facet category
that would be to lists as numpunct is to numbers. That might be as
simple as:
template <class charT>
class listpunct : public locale::facet {
public:
typedef charT char_type;
explicit listpunct(size_t refs = 0);
char_type start_delimiter() const;
char_type separator() const;
char_type end_delimiter() const;
static locale::id id;
protected:
// protected interface here...
};
start_delimiter()/end_delimiter() might return '\0' to indicate the
absence of a delimiter (I don't think it's sensible to allow separator()
to also do that).
A slightly more complex approach could allow each of the three functions
(and especially separator()) to return a string instead of a char.
One nice feature somehow in between of the two previous approaches would
be to allow the facet to introduce whitespaces, for example to allow a
complex to be output as "(1, 2)" instead of "(1,2)".
About tuples (as opposed to complexes) there's an additional (big)
problem: how to output strings? Strings might contain whitespaces and
also occurrences of the separator. To handle that, we could add to the
facet a function string_delimiter() the returns a std::string. The first
character is the actual string delimiter, the other characters, if
present, are to be used to provide an "escape" representation of the
string delimiter, when found inside the string. Maybe a traits_class and
a free function could be used to allow UDTs to behave as strings.
I think that the listpunct facet can be a good base to start with. In
fact I don't think we can go much further. For example we can't think of
list_get/list_put facets (like num_put/num_get) that could work with
tuples, because that would need virtual function templates.
Any ideas?
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]