<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
           "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<meta name="GENERATOR" content="TtH 2.90">
 

     
<title>  \const-correctness issues\\
        in clause~27: input/output library  \\
        (Document~\docno)</title>
 
<h1 align="center"> <tt>const</tt>-correctness issues<br />
        in clause&nbsp;27: input/output library  <br />
        (Document&nbsp;N1360, 02-0018) </h1>

<h3 align="center"> Walter Brown<br />
         Marc Paterno<br />
         Fermi National Accelerator Laboratory  </h3>

<h3 align="center">May&nbsp;7,&nbsp;2002 </h3>  

<h2> Abstract</h2>
We identify <tt>const</tt>-related inconsistencies
in the input/output component
of the C++&nbsp;standard library,
and propose changes to clause&nbsp;27 of the C++&nbsp;Standard
to address these issues.

<p>
This report is intended
to serve as the basis
for one or more defect reports
to be processed
by the committee's Library Working Group.

<p>

 <h2><a name="tth_sEc1">
1</a>&nbsp;&nbsp;Introduction</h2>

<p>
Pursuant to a commitment
made at the Redmond (October, 2001) meeting,
we undertook a review of clause&nbsp;27 of the C++&nbsp;Standard.
The initial motivation for this review
was Library Issue 73 (``<tt>is_open</tt> should be const''),
classified by the committee as NAD
with the sole rationale,
``This is a deliberate feature; const streams would be meaningless.''
We strongly disagreed with this disposition
(especially since other, similar, issues
were classified as DR's: 14, 110, 148, and 214)
and sought to re-open the issue.

<p>
We were gently made aware by other committee members
that clause&nbsp;27 was somewhat notorious
for its relative laxity
with respect to issues of <tt>const</tt>-correctness.
Further, we were less gently advised
that the committee
would prefer to avoid a piecemeal approach
in addressing such issues.

<p>
Accordingly, we undertook to locate and propose remedies
for all <tt>const</tt>-correctness problems
throughout clause&nbsp;27.
In particular,
we sought to identify
those member functions
in whose declarations
a useful <tt>const</tt>&nbsp;was missing,
or in which a <tt>const</tt>&nbsp;was present inappropriately.
This paper presents the results of our review,
one section for each of these two goals.
Within these sections,
we proceed sequentially
through the sections of clause&nbsp;27.

<p>

<p>

<p>
 <h2><a name="tth_sEc2">
2</a>&nbsp;&nbsp;Lack of <tt>const</tt>-qualification</h2>

<p>
Section summary:
none of the following member functions
is currently declared <tt>const</tt>,
but we believe that each should be.

<p>
The rationale for this set of recommendations is straightforward:
each of these functions
is responsible for reporting
on the existing state of its respective class instance
and none of these functions
need alter the instance's logical state to do so.

<p>
Before presenting the annotated list of functions in this category,
we wish to show a motivating example.
This rather elementary example is intended to contradict the claim,
evidently previously endorsed by the committee,
that ``const streams would be meaningless'';
it seems clear that the following code is meaningful indeed:

<blockquote>
<pre>
void  f( const std::istream&amp;  is )  {
  if( is.in_avail() &#62; 0 )  { /*...*/ }
}

</pre></blockquote>

<p>
The failure of such code to compile
presents a surprise to users.

<p>
To avoid duplication, we stress here that, to the best of our
understanding and belief, each of the following functions is
intended solely to report on some aspect of the state of its
invoking object, and can do so without mutating that instance. In
some cases, we believe, functions were not previously declared
<tt>const</tt>&nbsp;because they seemed to need invoke other non-<tt>const</tt>&nbsp;functions. We have addressed all of these, too, either within this
section or in the next section.

<p>
     <h3><a name="tth_sEc2.1">
2.1</a>&nbsp;&nbsp;<tt>basic_streambuf&lt;&#62;::in_avail</tt></h3>

<p>
&#167;27.5.2 and &#167;27.5.2.2.3

<p>
Proposed declaration:
<tt>streamsize in_avail() const;</tt>

<p>
     <h3><a name="tth_sEc2.2">
2.2</a>&nbsp;&nbsp;<tt>basic_streambuf&lt;&#62;::showmanyc</tt></h3>

<p>
&#167;27.5.2 and &#167;27.5.2.4.3

<p>
Proposed declaration:
<tt>virtual streamsize showmanyc() const;</tt>

<p>
     <h3><a name="tth_sEc2.3">
2.3</a>&nbsp;&nbsp;<tt>basic_istream&lt;&#62;::tellg</tt></h3>

<p>
We strongly believe that this function should be declared <tt>const</tt>.
However, the ramifications of this change require more study
and so we are not now proposing this change.
We expect to do so via a future paper.

<p>

<p>
     <h3><a name="tth_sEc2.4">
2.4</a>&nbsp;&nbsp;<tt>basic_ostream&lt;&#62;</tt>::<tt>tellp</tt></h3>

<p>
We strongly believe that this function should be declared <tt>const</tt>.
As is the case for <tt>tellg</tt> above,
the ramifications of this change require more study
and so we are not now proposing this change.
We expect to do so via a future paper.

<p>

<p>
     <h3><a name="tth_sEc2.5">
2.5</a>&nbsp;&nbsp;<tt>basic_filebuf&lt;&#62;::showmanyc</tt></h3>

<p>
&#167;27.8.1.1 and &#167;27.8.1.4 above paragraph&nbsp;1

<p>
Proposed declaration:
<tt>virtual streamsize showmanyc() const;</tt>

<p>
     <h3><a name="tth_sEc2.6">
2.6</a>&nbsp;&nbsp;<tt>basic_ifstream&lt;&#62;::is_open</tt></h3>

<p>
&#167;27.8.1.5 and &#167;27.8.1.7 above paragraph&nbsp;2

<p>
Proposed declaration:
<tt>bool is_open() const;</tt>

<p>
     <h3><a name="tth_sEc2.7">
2.7</a>&nbsp;&nbsp;<tt>basic_ofstream&lt;&#62;::is_open</tt></h3>

<p>
&#167;27.8.1.8 and &#167;27.8.1.10 above paragraph&nbsp;2

<p>
Proposed declaration:
<tt>bool is_open() const;</tt>

<p>
     <h3><a name="tth_sEc2.8">
2.8</a>&nbsp;&nbsp;<tt>basic_fstream&lt;&#62;::is_open</tt></h3>

<p>
&#167;27.8.1.11 and &#167;27.8.1.13 above paragraph&nbsp;2

<p>
Proposed declaration:
<tt>bool is_open() const;</tt>

<p>
 <h2><a name="tth_sEc3">
3</a>&nbsp;&nbsp;Excessive <tt>const</tt>-qualification</h2>

<p>
Section summary:
the following member functions are declared <tt>const</tt>,
yet return non-<tt>const</tt>&nbsp;pointers.
We believe, with one exception,
that all of these are troublesome
in that they allow code
which is likely to surprise the user.

<p>
We believe the guarantee provided by a <tt>const</tt>&nbsp;member function
is most valuable to users
when it refers to ``logical <tt>const</tt>-ness'',
rather than to ``bitwise <tt>const</tt>-ness'':
one should not be able to change the observable state
of on object to which one has only <tt>const</tt>-qualified access.
To this end, we believe that a <tt>const</tt>&nbsp;member function
should only rarely, if ever,
return a non-<tt>const</tt>&nbsp;pointer (or reference) to a data member,
because this allows a user to change the state of the invoking object
even when given only <tt>const</tt>&nbsp;access to that object.
A single example will suffice to demonstrate this:

<p>
Under the current wording, the function
<tt>basic_ios&lt;charT,traits&#62;::rdbuf</tt> is declared <tt>const</tt>,
but returns a non-<tt>const</tt>&nbsp;pointer. This means that the following
code is well-formed:

<p>

<blockquote>
<pre>
void f(const std::basic_ios&lt;char&#62;&amp;  str) {
  str.rdbuf()-&#62;sputc('x');
}

</pre>
</blockquote>

<p>
This function <tt>f</tt> will alter the stream <i>str</i>,
even though <i>str</i>,
as <tt>f</tt>'s argument,
is declared <tt>const</tt>.
This behavior is very likely to surprise a user of <tt>f</tt>.

<p>
We propose that all of the problems of this kind
can be solved via the application of a standard idiom:
replacing each such misguided member function
by a pair of member functions such that

<ul><p>
<li> the one replacement is declared <tt>const</tt>&nbsp;and returns a <tt>const</tt>&nbsp;pointer, and</li>
<p>
<li> the other is not declared <tt>const</tt>&nbsp;and returns a non-<tt>const</tt>&nbsp;pointer.</li>
</ul>

<p>
Under our proposal,
such a function <tt>f</tt> would not compile.
Such a change could break currently working code.
However, the purpose of this proposal is to make such code illegal:
if the implementer of <tt>f</tt>
wishes to modify the object it is passed,
then the argument <i>str</i> should not be declared <tt>const</tt>.

<p>
We stress, to eliminate considerable duplicate verbiage,
that each of the following functions is declared <tt>const</tt>&nbsp;at present,
yet returns a non-<tt>const</tt>&nbsp;pointer.

<p>
     <h3><a name="tth_sEc3.1">
3.1</a>&nbsp;&nbsp;<tt>basic_ios&lt;&#62;::operator void*</tt></h3>

<p>
&#167;27.4.4

<p>
We draw attention to the fact that,
although <tt>operator void*</tt> is declared <tt>const</tt>,
and while the return value is not declared to be <tt>const</tt>,
we believe that no change is necessary.
The returned pointer is not the address of a data member;
so the lack of <tt>const</tt>-ness in the return type seems innocuous.

<p>
     <h3><a name="tth_sEc3.2">
3.2</a>&nbsp;&nbsp;<tt>basic_ios&lt;&#62;</tt> member functions</h3>

<p>
&#167;27.4.4 and &#167;27.4.4.2

<p>
We propose to replace each of
<tt>tie</tt> and <tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_ostream&lt;charT,traits&#62;*   tie();
const basic_ostream&lt;charT,traits&#62;*   tie() const;

      basic_streambuf&lt;charT,traits&#62;* rdbuf();
const basic_streambuf&lt;charT,traits&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.3">
3.3</a>&nbsp;&nbsp;<tt>basic_streambuf&lt;&#62;</tt> Get area</h3>

<p>
&#167;27.5.2 and &#167;27.5.2.3.1

<p>
We propose to replace each of
<tt>eback</tt>, <tt>gptr</tt>, and <tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      char_type* eback();
const char_type* eback() const;

      char_type* gptr();
const char_type* gptr() const;

      char_type* egptr();
const char_type* egptr() const;

</pre>

<p>
     <h3><a name="tth_sEc3.4">
3.4</a>&nbsp;&nbsp;<tt>basic_streambuf&lt;&#62;</tt> Put area</h3>

<p>
&#167;27.5.2 and &#167;27.5.2.3.2

<p>
We propose to replace each of
<tt>pbase</tt>, <tt>pptr</tt>, and <tt>epptr</tt>
by a pair of functions:

<p>

<pre>
      char_type* pbase();
const char_type* pbase() const;

      char_type* pptr();
const char_type* pptr() const;

      char_type* epptr();
const char_type* epptr() const;

</pre>

<p>
     <h3><a name="tth_sEc3.5">
3.5</a>&nbsp;&nbsp;<tt>basic_istringstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.7.2 and &#167;27.7.2.2

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf();
const basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.6">
3.6</a>&nbsp;&nbsp;<tt>basic_ostringstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.7.3 and &#167;27.7.3.2

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf();
const basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.7">
3.7</a>&nbsp;&nbsp;<tt>basic_stringstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.7.4 and &#167;27.7.6

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf();
const basic_stringbuf&lt;charT,traits,Allocator&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.8">
3.8</a>&nbsp;&nbsp;<tt>basic_ifstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.8.1.5 and &#167;27.8.1.7 above paragraph&nbsp;1

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_filebuf&lt;charT,traits&#62;* rdbuf();
const basic_filebuf&lt;charT,traits&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.9">
3.9</a>&nbsp;&nbsp;<tt>basic_ofstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.8.1.8 and &#167;27.8.1.10 above paragraph 1

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_filebuf&lt;charT,traits&#62;* rdbuf();
const basic_filebuf&lt;charT,traits&#62;* rdbuf() const;

</pre>

<p>
     <h3><a name="tth_sEc3.10">
3.10</a>&nbsp;&nbsp;<tt>basic_fstream&lt;&#62;</tt> member</h3>

<p>
&#167;27.8.1.11 and &#167;27.8.1.13 above paragraph 1

<p>
We propose to replace
<tt>rdbuf</tt>
by a pair of functions:

<p>

<pre>
      basic_filebuf&lt;charT,traits&#62;* rdbuf();
const basic_filebuf&lt;charT,traits&#62;* rdbuf() const;

</pre>

<p>

<br /><br /><hr /><small>File translated from
T<sub><font size="-1">E</font></sub>X
by <a href="http://hutchinson.belmont.ma.us/tth/">
T<sub><font size="-1">T</font></sub>H</a>,
version 2.90.<br />On 07 May 2002, 13:36.</small>
</html>
