This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
2984.put_money(99)
is unnecessarily undefined
Section: 31.7.8 [ext.manip] Status: New Submitter: Jonathan Wakely Opened: 2017-06-22 Last modified: 2017-06-26
Priority: 3
View all other issues in [ext.manip].
View all issues with New status.
Discussion:
[ext.manip] p5 says:
Requires: The type
moneyT
shall be eitherlong double
or a specialization of thebasic_string
template (Clause 24).
This means that put_money(99)
, put_money(99.)
, put_money("99")
, and put_money(string_view{"99"})
are all undefined, when in practice they will compile fine and do the right thing, converting the argument to long double
or std::string
as needed.
long double
or a std::basic_string
, but that will unnecessarily break code that works fine today. We should accept types convertible to long double
or the relevant money_put
facet's string_type
(which is not known until we attempt to write the unspecified type to an ostream). The requirement is also insufficient, because cout << put_money(wstring(L"99"))
won't compile on any implementation, despite the argument type being a specialization of basic_string
. This same problem exists for std::get_money
.
[2017-06-24, Daniel comments and provides wording]
The wording changes below are supposed to support all moneyT
types that are convertible to either long double
or to money_put/get<Ch, o/istreambuf_iterator<Ch, Tr>>::string_type
(but not to both), where Ch
and Tr
are determined by the concrete instantiated specialization of the exposition-only function template f
that is used to specify the semantics of put_money
and get_money
, respectively. XOR-ing the requirements outlaws types that are convertible to both, which would cause an ambiguity unless we would provide wording that would introduce an ordered application of these convertibility constraints. This is the rationale for the seemingly odd new Remarks formulation. Note also, that the wording provided below intentionally attempts to distinguish between the statically testable conditions based on the is_convertible_v
expressions within the Remarks: element and the well-defined runtime behaviour requirement of the actually provided argument of deduced type moneyT
within the pre-existing Requires: element. Another point worth pointing out is that the wording attempts to fix an currently existing ambiguity of the meaning of the type moneyT
(and to a lesser extend for charT
and traits
) as either the template parameter of put/get_money
or that of the corresponding template argument of the exposition-only f
templates. The revised form makes it clearer that it refers to the latter.
put_money(99)
, put_money(99.)
, and put_money("99")
, but not yet for put_money(string_view{"99"})
, because string_view
is not convertible to string
. To realize support for the latter, this wording approach could be extended by referring to is_constructible
instead of is_convertible
, though.
Proposed resolution:
This wording is relative to N4659.
Edit 31.7.8 [ext.manip] as indicated:
template <class moneyT> unspecified get_money(moneyT& mon, bool intl = false);-?- For an expression
-2- Requires: The typein >> get_money(mon, intl)
described below, letMo
,Ch
, andTr
be the deduced template argument types of the template parametersmoneyT
,charT
, andtraits
, respectively, of the instantiated specialization of the templatef
.moneyT
shall be eitherlong double
or a specialization of thebasic_string
template (Clause 27 [strings])Mo
shall be either convertible tolong double
or shall be convertible tomoney_get<Ch, istreambuf_iterator<Ch, Tr>>::string_type
. -?- Remarks: Ifis_convertible_v<Mo, long double> == is_convertible_v<Mo, money_get<Ch, istreambuf_iterator<Ch, Tr>>::string_type>
, the program is ill-formed. -3- Effects: The expressionin >> get_money(mon, intl)
described below behaves as a formatted input function (31.7.5.3.1 [istream.formatted.reqmts]). -4- Returns: An object of unspecified type such that ifin
is an object of typebasic_istream< charT Ch, traits Tr>
then the expressionin >> get_money(mon, intl)
behaves as if it calledf(in, mon, intl)
, where the functionf
is defined as:template <class charT, class traits, class moneyT> void f(basic_ios<charT, traits>& str, moneyT& mon, bool intl) { using Iter = istreambuf_iterator<charT, traits>; using MoneyGet = money_get<charT, Iter>; ios_base::iostate err = ios_base::goodbit; const MoneyGet& mg = use_facet<MoneyGet>(str.getloc()); mg.get(Iter(str.rdbuf()), Iter(), intl, str, err, mon); if (ios_base::goodbit != err) str.setstate(err); }The expression
in >> get_money(mon, intl)
shall have typebasic_istream< charT Ch, traits Tr>&
and valuein
.template <class moneyT> unspecified put_money(const moneyT& mon, bool intl = false);-?- For an expression
-5- Requires: The typeout << put_money(mon, intl)
described below, letMo
,Ch
, andTr
be the deduced template argument types of the template parametersmoneyT
,charT
, andtraits
, respectively, of the instantiated specialization of the templatef
.moneyT
shall be eitherlong double
or a specialization of thebasic_string
template (Clause 27 [strings])Mo
shall be either convertible tolong double
or shall be convertible tomoney_put<Ch, ostreambuf_iterator<Ch, Tr>>::string_type
. -?- Remarks: Ifis_convertible_v<Mo, long double> == is_convertible_v<Mo, money_put<Ch, ostreambuf_iterator<Ch, Tr>>::string_type>
, the program is ill-formed. -6- Returns: An object of unspecified type such that ifout
is an object of typebasic_ostream< charT Ch, traits Tr>
then the expressionout << put_money(mon, intl)
behaves as a formatted output function (31.7.6.3.1 [ostream.formatted.reqmts]) that callsf(out, mon, intl)
, where the functionf
is defined as:template <class charT, class traits, class moneyT> void f(basic_ios<charT, traits>& str, const moneyT& mon, bool intl) { using Iter = ostreambuf_iterator<charT, traits>; using MoneyPut = money_put<charT, Iter>; const MoneyPut& mp = use_facet<MoneyPut>(str.getloc()); const Iter end = mp.put(Iter(str.rdbuf()), intl, str, str.fill(), mon); if (end.failed()) str.setstate(ios::badbit); }The expression
out << put_money(mon, intl)
shall have typebasic_ostream< charT Ch, traits Tr>&
and valueout
.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4