<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2984: put_money(99) is unnecessarily undefined</title>
<meta property="og:title" content="Issue 2984: put_money(99) is unnecessarily undefined">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2984.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#New">New</a> status.</em></p>
<h3 id="2984"><a href="lwg-active.html#2984">2984</a>. <code>put_money(99)</code> is unnecessarily undefined</h3>
<p><b>Section:</b> 31.7.8 <a href="https://wg21.link/ext.manip">[ext.manip]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2017-06-22 <b>Last modified:</b> 2017-06-26</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#ext.manip">issues</a> in [ext.manip].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
[ext.manip] p5 says:
</p>
<blockquote><p>
<i>Requires:</i> The type <code>moneyT</code> shall be either <code>long double</code> or a specialization of the 
<code>basic_string</code> template (Clause 24).
</p></blockquote>
<p>
This means that <code>put_money(99)</code>, <code>put_money(99.)</code>, <code>put_money("99")</code>, and 
<code>put_money(string_view{"99"})</code> are all undefined, when in practice they will compile fine and 
do the right thing, converting the argument to <code>long double</code> or <code>std::string</code> as needed.
<p/>
We could change it to be "otherwise the program is ill-formed", or to remove the function templates from overload 
resolution when the argument is not <code>long double</code> or a <code>std::basic_string</code>, but that will unnecessarily 
break code that works fine today. We should accept types convertible to <code>long double</code> or the relevant 
<code>money_put</code> facet's <code>string_type</code> (which is not known until we attempt to write the unspecified 
type to an ostream).
<p/>
The requirement is also insufficient, because <code>cout &lt;&lt; put_money(wstring(L"99"))</code> won't compile on any 
implementation, despite the argument type being a specialization of <code>basic_string</code>. This same problem exists 
for <code>std::get_money</code>.
</p>

<p><i>[2017-06-24, Daniel comments and provides wording]</i></p>

<p>
The wording changes below are supposed to support all <code>moneyT</code> types that are convertible to either 
<code>long double</code> or to <code>money_put/get&lt;Ch, o/istreambuf_iterator&lt;Ch, Tr&gt;&gt;::string_type</code> 
(but not to both), where <code>Ch</code> and <code>Tr</code> are determined by the concrete instantiated specialization of the 
exposition-only function template <code>f</code> that is used to specify the semantics of <code>put_money</code> and 
<code>get_money</code>, 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 <i>Remarks</i> formulation. Note also,
that the wording provided below intentionally attempts to distinguish between the statically testable
conditions based on the <code>is_convertible_v</code> expressions within the <i>Remarks:</i> element and the well-defined 
runtime behaviour requirement of the actually provided argument of deduced type <code>moneyT</code> within the 
pre-existing <i>Requires:</i> element. Another point worth pointing out is that the wording attempts to fix an
currently existing ambiguity of the meaning of the type <code>moneyT</code> (and to a lesser extend for <code>charT</code> and
<code>traits</code>) as either the template parameter of <code>put/get_money</code> or that of the corresponding template
argument of the exposition-only <code>f</code> templates. The revised form makes it clearer that it refers to the latter.
<p/>
It should be emphasized that this extension of the current wording would provide support for <code>put_money(99)</code>, 
<code>put_money(99.)</code>, and <code>put_money("99")</code>, but <em>not</em> yet for <code>put_money(string_view{"99"})</code>, 
because <code>string_view</code> is not convertible to <code>string</code>. To realize support for the latter, this wording 
approach could be extended by referring to <code>is_constructible</code> instead of <code>is_convertible</code>, though.
</p>


<p id="res-2984"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4659">N4659</a>.
</p>

<ol>
<li><p>Edit 31.7.8 <a href="https://wg21.link/ext.manip">[ext.manip]</a> as indicated:</p>

<blockquote>
<pre>
template &lt;class moneyT&gt; <i>unspecified</i> get_money(moneyT&amp; mon, bool intl = false);
</pre>
<blockquote>
<p>
<ins>-?- For an expression <code>in &gt;&gt; get_money(mon, intl)</code> described below, let <code><i>Mo</i></code>, 
<code><i>Ch</i></code>, and <code><i>Tr</i></code> be the deduced template argument types of the template parameters 
<code>moneyT</code>, <code>charT</code>, and <code>traits</code>, respectively, of the instantiated specialization of the 
template <code>f</code>.</ins>
<p/>
-2- <i>Requires:</i> <del>The type <code>moneyT</code> shall be either <code>long double</code> or a specialization of the 
<code>basic_string</code> template (Clause 27 <a href="https://wg21.link/strings">[strings]</a>)</del><ins><code><i>Mo</i></code>
shall be either convertible to <code>long double</code> or shall be convertible to 
<code>money_get&lt;<i>Ch</i>, istreambuf_iterator&lt;<i>Ch</i>, <i>Tr</i>&gt;&gt;::string_type</code></ins>.
<p/>
<ins>-?- <i>Remarks:</i> If <code>is_convertible_v&lt;<i>Mo</i>, long double&gt; == is_convertible_v&lt;<i>Mo</i>, 
money_get&lt;<i>Ch</i>, istreambuf_iterator&lt;<i>Ch</i>, <i>Tr</i>&gt;&gt;::string_type&gt;</code>,
the program is ill-formed.</ins>
<p/>
-3- <i>Effects:</i> The expression <code>in &gt;&gt; get_money(mon, intl)</code> described below behaves as 
a formatted input function (31.7.5.3.1 <a href="https://wg21.link/istream.formatted.reqmts">[istream.formatted.reqmts]</a>).
<p/>
-4- <i>Returns:</i> An object of unspecified type such that if <code>in</code> is an object of type 
<code>basic_istream&lt;<del>charT</del><ins><i>Ch</i></ins>, <del>traits</del><ins><i>Tr</i></ins>&gt;</code> then 
the expression <code>in &gt;&gt; get_money(mon, intl)</code> behaves as if it called <code>f(in, mon, intl)</code>, where 
the function <code>f</code> is defined as:
</p>
<blockquote><pre>
template &lt;class charT, class traits, class moneyT&gt;
void f(basic_ios&lt;charT, traits>&amp; str, moneyT&amp; mon, bool intl) {
  using Iter = istreambuf_iterator&lt;charT, traits&gt;;
  using MoneyGet = money_get&lt;charT, Iter&gt;;
  ios_base::iostate err = ios_base::goodbit;
  const MoneyGet&amp; mg = use_facet&lt;MoneyGet>(str.getloc());
  mg.get(Iter(str.rdbuf()), Iter(), intl, str, err, mon);
  if (ios_base::goodbit != err)
    str.setstate(err);
}
</pre></blockquote>
<p>
The expression <code>in &gt;&gt; get_money(mon, intl)</code> shall have type 
<code>basic_istream&lt;<del>charT</del><ins><i>Ch</i></ins>, <del>traits</del><ins><i>Tr</i></ins>&gt;&amp;</code> 
and value <code>in</code>.
</p>
</blockquote>
<pre>
template &lt;class moneyT&gt; <i>unspecified</i> put_money(const moneyT&amp; mon, bool intl = false);
</pre>
<blockquote>
<p>
<ins>-?- For an expression <code>out &lt;&lt; put_money(mon, intl)</code> described below, let <code><i>Mo</i></code>, 
<code><i>Ch</i></code>, and <code><i>Tr</i></code> be the deduced template argument types of the template parameters 
<code>moneyT</code>, <code>charT</code>, and <code>traits</code>, respectively, of the instantiated specialization of the 
template <code>f</code>.</ins>
<p/>
-5- <i>Requires:</i> <del>The type <code>moneyT</code> shall be either <code>long double</code> or a specialization of the 
<code>basic_string</code> template (Clause 27 <a href="https://wg21.link/strings">[strings]</a>)</del><ins><code><i>Mo</i></code>
shall be either convertible to <code>long double</code> or shall be convertible to 
<code>money_put&lt;<i>Ch</i>, ostreambuf_iterator&lt;<i>Ch</i>, <i>Tr</i>&gt;&gt;::string_type</code></ins>.
<p/>
<ins>-?- <i>Remarks:</i> If <code>is_convertible_v&lt;<i>Mo</i>, long double&gt; == is_convertible_v&lt;<i>Mo</i>, 
money_put&lt;<i>Ch</i>, ostreambuf_iterator&lt;<i>Ch</i>, <i>Tr</i>&gt;&gt;::string_type&gt;</code>,
the program is ill-formed.</ins>
<p/>
-6- <i>Returns:</i> An object of unspecified type such that if <code>out</code> is an object of type 
<code>basic_ostream&lt;<del>charT</del><ins><i>Ch</i></ins>, <del>traits</del><ins><i>Tr</i></ins>&gt;</code> then 
the expression <code>out &lt;&lt; put_money(mon, intl)</code> behaves as a formatted output function
(31.7.6.3.1 <a href="https://wg21.link/ostream.formatted.reqmts">[ostream.formatted.reqmts]</a>) that calls <code>f(out, mon, intl)</code>, where the function <code>f</code> 
is defined as:
</p>
<blockquote><pre>
template &lt;class charT, class traits, class moneyT&gt;
void f(basic_ios&lt;charT, traits&gt;&amp; str, const moneyT&amp; mon, bool intl) {
  using Iter = ostreambuf_iterator&lt;charT, traits&gt;;
  using MoneyPut = money_put&lt;charT, Iter&gt;;
  const MoneyPut&amp; mp = use_facet&lt;MoneyPut>(str.getloc());
  const Iter end = mp.put(Iter(str.rdbuf()), intl, str, str.fill(), mon);
  if (end.failed())
    str.setstate(ios::badbit);
}
</pre></blockquote>
<p>
The expression <code>out &lt;&lt; put_money(mon, intl)</code> shall have type 
<code>basic_ostream&lt;<del>charT</del><ins><i>Ch</i></ins>, <del>traits</del><ins><i>Tr</i></ins>&gt;&amp;</code>
and value <code>out</code>.
</p>
</blockquote>
</blockquote>
</li>
</ol>




</body>
</html>
