Doc. no. | N2072=06-0142 |
Date: | 2006-09-09 |
Project: | Programming Language C++ |
Reply to: | Martin Sebor |
The C++ standard library facet class templates provide a robust interface to the localization library, one that lends itself well to being implemented and used with efficiency in mind. The get and put parsing and formatting facets specifically are especially well suited to be used as the engine of a higher-level and more convenient interfaces such as iostreams. However, due to the large number and complexity of their arguments and to the complexities of the error handling involved they are less than ideal for direct use by programs.
The num_get
and num_put
facets
are a good example of where this design works well and
does not pose any serious problems to programs. Nearly
every C++ program relies on the services provided by the
facets by virtue of making calls to the arithmetic
iostream extractor and inserter operators, yet only very
few programs ever need to access these facets directly. In
fact, many C++ programmers are not even aware that the
facets exist.
Unfortunately, the num_get
and
num_put
facets mentioned above are the only
such example in the C++ localization library. No
convenient interface similar to the arithmetic inserters
and extractors exists to make it as easy to parse or
format monetary (or time) sequences and values,
respectively, as it is for arithmetic types. C++ programs
that need to do so must code directly to the low-level
interfaces of the monetary and time get and
put facets. We believe that these interfaces,
while powerful, are cumbersome enough to use that they
deter most C++ programmers from taking advantage of their
functionality.
In this paper we propose a convenient interface to the
parsing and formatting facilities provided by the
money_get
and money_put
facets,
one that we believe is nearly as easy to use as the
arithmetic inserters and extractors. The proposed
interface takes the form of a pair of matching
manipulators that, when used with the existing extraction
and insertion operators, provide the desired simplicity
and ease of use. Note that the manipulator approach was
chosen since the extraction and insertion operators are
already overloaded on both types commonly used to
represent monetary values, that is long
double
and basic_string
.
Note: While independent of one another, this proposal should be reviewed and considered in conjunction with N2071=06-0140 – Iostream manipulators for convenient extraction and insertion of struct tm objects.
Add a new section after lib.std.manip titled Extended Manipulators [lib.ext.manip], with the following text:
The header <iomanip>
also defines a
number of functions that use the smanip type to
provide extractors and inserters that allow for the
extraction and parsing of monetary sequences and values,
respectively.
The type designated smanip in each of the following function descriptions is implementation-defined and may be different for each function.
template <class moneyT>
smanip get_money (moneyT& mon, bool intl = false);
Requires: The typemoneyT
is eitherlong double
or a specialization ofbasic_string<charT, char_traits<charT>, allocator<charT>>
on a valid character typecharT
.
Returns: An objects
of unspecified type such that ifin
is an object of (derived from)basic_istream<charT, traits>
and the type ofmon
ismoneyT
then the expressionin >> get_money(mon, intl)
behaves as iff(str, mon, intl)
were evaluated wheref
may be defined similarly to the following (exception handling omitted):
template <class charT, class traits, class moneyT> void f (basic_ios<charT, traits>& str, moneyT& mon, bool intl) { typedef istreambuf_iterator<charT> Iter; typedef money_get<charT, Iter> MoneyGet; ios_base::iostate err = ios_base::goodbit; const MoneyGet &mg = use_facet<MoneyGet>(str.getloc ()); mg.get (Iter (str.rdbuf ()), Iter (), intl, strm, err, mon); if (ios_base::goodbit != err) str.setstate (err); }
Note: The type of thein >> s
expression isbasic_istream<charT, traits>&
and its value is in.
template <class charT, class moneyT>
smanip put_money (const moneyT& mon, bool intl = false);
Requires: The typemoneyT
is eitherlong double
or a specialization ofbasic_string<charT, char_traits<charT>, allocator<charT>>
on a valid character typecharT
.
Returns: An objects
of unspecified type such that ifout
is an object of (derived from)basic_ostream<charT, traits>
, the type ofmon
ismoneyT
and the type ofintl
isbool
then the expressionout << s
behaves as iff(s, mon, intl)
were evaluated wheref
may be defined similarly to the following (exception handling omitted):
template <class charT, class traits, class moneyT> void f (basic_ios<charT, traits>& str, const moneyT& mon, bool intl) { typedef ostreambuf_iterator<charT> Iter; typedef money_put<charT, Iter> MoneyPut; const MoneyPut &mp = use_facet<MoneyPut>(str.getloc ()); const Iter end = tp.put (Iter (str.rdbuf ()), intl, str, str.fill (), mon); if (end.failed ()) str.setstate (ios_base::badbit); }
Note: The type of theout << s
expression isbasic_ostream<charT, traits>&
and its value isout
.
A reference implementation of this extension is available for review in the Open Source Apache C++ Standard Library in the form of a complete example program.