<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 44: Iostreams use operator== on int_type values</title>
<meta property="og:title" content="Issue 44: Iostreams use operator== on int_type values">
<meta property="og:description" content="C++ library issue. Status: CD1">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue44.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#CD1">CD1</a> status.</em></p>
<h3 id="44"><a href="lwg-defects.html#44">44</a>. Iostreams use operator== on int_type values</h3>
<p><b>Section:</b> 31 <a href="https://wg21.link/input.output">[input.output]</a> <b>Status:</b> <a href="lwg-active.html#CD1">CD1</a>
 <b>Submitter:</b> Nathan Myers <b>Opened:</b> 1998-08-06 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#input.output">issues</a> in [input.output].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#CD1">CD1</a> status.</p>
<p><b>Discussion:</b></p>
<p>Many of the specifications for iostreams specify that character
values or their int_type equivalents are compared using operators ==
or !=, though in other places traits::eq() or traits::eq_int_type is
specified to be used throughout. This is an inconsistency; we should
change uses of == and != to use the traits members instead. </p>


<p id="res-44"><b>Proposed resolution:</b></p>

<p><i>[Pre-Kona: Dietmar supplied wording]</i></p>


<p>List of changes to clause 27:</p>
<ol>
<li>
   In lib.basic.ios.members paragraph 13 (postcondition clause for
   'fill(cT)') change

<blockquote><pre>
     fillch == fill()
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(fillch, fill())
</pre></blockquote>


</li>
<li>
   In lib.istream.unformatted paragraph 7 (effects clause for
   'get(cT,streamsize,cT)'), third bullet, change

<blockquote><pre>
     c == delim for the next available input character c
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(c, delim) for the next available input character c
</pre></blockquote>

</li>
<li>
   In lib.istream.unformatted paragraph 12 (effects clause for
   'get(basic_streambuf&lt;cT,Tr>&amp;,cT)'), third bullet, change

<blockquote><pre>
     c == delim for the next available input character c
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(c, delim) for the next available input character c
</pre></blockquote>

</li>
<li>
   In lib.istream.unformatted paragraph 17 (effects clause for
   'getline(cT,streamsize,cT)'), second bullet, change

<blockquote><pre>
     c == delim for the next available input character c
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(c, delim) for the next available input character c
  </pre></blockquote>

</li>
<li>
   In lib.istream.unformatted paragraph 24 (effects clause for
   'ignore(int,int_type)'), second bullet, change

<blockquote><pre>
     c == delim for the next available input character c
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq_int_type(c, delim) for the next available input
     character c
</pre></blockquote>
  
</li>
<li>
   In lib.istream.unformatted paragraph 25 (notes clause for
   'ignore(int,int_type)'), second bullet, change

<blockquote><pre>
     The last condition will never occur if delim == traits::eof()
</pre></blockquote>

   to

<blockquote><pre>
     The last condition will never occur if
     traits::eq_int_type(delim, traits::eof()).
</pre></blockquote>

</li>
<li>
   In lib.istream.sentry paragraph 6 (example implementation for the
   sentry constructor) change

<blockquote><pre>
     while ((c = is.rdbuf()->snextc()) != traits::eof()) {
</pre></blockquote>

   to

<blockquote><pre>
     while (!traits::eq_int_type(c = is.rdbuf()->snextc(), traits::eof())) {
</pre></blockquote>

</li>
</ol>

<p>List of changes to Chapter 21:</p>

<ol>
<li>
   In lib.string::find paragraph 1 (effects clause for find()),
   second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>

</li>
<li>
   In lib.string::rfind paragraph 1 (effects clause for rfind()),
   second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>

</li>
<li>
   In lib.string::find.first.of paragraph 1 (effects clause for
   find_first_of()), second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>

</li>
<li>
   In lib.string::find.last.of paragraph 1 (effects clause for
   find_last_of()), second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>

</li>
<li>
   In lib.string::find.first.not.of paragraph 1 (effects clause for
   find_first_not_of()), second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>
</li>

<li>
   In lib.string::find.last.not.of paragraph 1 (effects clause for
   find_last_not_of()), second bullet, change

<blockquote><pre>
     at(xpos+I) == str.at(I) for all elements ...
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(at(xpos+I), str.at(I)) for all elements ...
</pre></blockquote>
</li>

<li>
   In lib.string.ios paragraph 5 (effects clause for getline()),
   second bullet, change

<blockquote><pre>
     c == delim for the next available input character c 
</pre></blockquote>

   to

<blockquote><pre>
     traits::eq(c, delim) for the next available input character c 
</pre></blockquote>
</li>

</ol>

<p>Notes:</p>
<ul>
<li>
  Fixing this issue highlights another sloppyness in
  lib.istream.unformatted paragraph 24: this clause mentions a "character"
  which is then compared to an 'int_type' (see item 5. in the list
  below). It is not clear whether this requires explicit words and
  if so what these words are supposed to be. A similar issue exists,
  BTW, for operator*() of istreambuf_iterator which returns the result
  of sgetc() as a character type (see lib.istreambuf.iterator::op*
  paragraph 1), and for operator++() of istreambuf_iterator which
  passes the result of sbumpc() to a constructor taking a char_type
  (see lib.istreambuf.iterator::operator++ paragraph 3). Similarily, the
  assignment operator ostreambuf_iterator passes a char_type to a function
  taking an int_type (see lib.ostreambuf.iter.ops paragraph 1).
</li>
<li>
  It is inconsistent to use comparisons using the traits functions in
  Chapter 27 while not using them in Chapter 21, especially as some
  of the inconsistent uses actually involve streams (eg. getline() on
  streams). To avoid leaving this issue open still longer due to this
  inconsistency (it is open since 1998), a list of changes to Chapter
  21 is below.
</li>
<li>
  In Chapter 24 there are several places with statements like "the end
  of stream is reached (streambuf_type::sgetc() returns traits::eof())"
  (lib.istreambuf.iterator paragraph 1, lib.ostreambuf.iter.ops
  paragraph 5). It is unclear whether these should be clarified to use
  traits::eq_int_type() for detecting traits::eof().
</li>
</ul>






</body>
</html>
