<html>

<head>
<title>Constant View: A proposal for a 'std::as_const' helper function template</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  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}
</style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P0007R1</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2015-10-22</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">ADAM David Alan Martin (&lt;<a href="mailto:adamartin@FreeBSD.org">adamartin@FreeBSD.org</a>&gt;)</td>
</tr>
<tr>
  <td/>
  <td align="left">Alisdair Meredith      (&lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;)</td>
</tr>
</table>

<h1>Constant View: A proposal for a <code>std::as_const</code> helper function template</h1>

<h3>Version History</h3>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4380.html">N4380</a> Original submission</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0007r0.html">P0007R0</a> Added proposed wording  (this paper)</li>
</ul>

<h2><a name="1.0">Revision History</a></h2>

<h3><a name="1.1"><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4380.html">N4380</a> Original Submission</a></h3>

<h3><a name="1.2"><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0007r0.html">P0007R0</a> Revision 0</a></h3>
<p>
Added proposed wording for the standard.
</p>

<h3><a name="1.3"><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0007r1.html">P0007R1</a> Revision 1  (this paper)</a></h3>

<p>
This paper was presented to LEWG at the Lenexa meeting in May 2015, and greeted favorably.
It was held back from moving to LWG only for the lack of proposed wording, added in this update.
</p>

<h2><a name="1.0">I. Table of Contents</a></h2>
<ul>
<li><a href="#1.0">I. Table of Contents</a></li>
<li><a href="#2.0">II. Introduction</a></li>
<li><a href="#3.0">III. Background</a></li>
<li><a href="#4.0">IV. Motivation</a></li>
<li><a href="#5.0">V. Alternatives</a></li>
<li><a href="#6.0">VI. Discussion</a></li>
<ul>
  <li><a href="#6.1"><code>const_cast&lt; const T &amp; &gt;( object )</code></li>
  <li><a href="#6.2"><code>const_cast&lt; std::add_const&lt; decltype( object ) &gt;::type &amp; &gt;( object )</code></li>
  <li><a href="#6.3">Extend the language with <code>const_cast( object )</code></li>
  <li><a href="#6.4">Extend the language with <code>(const) object</code></li>
  <li><a href="#6.5">Library function, <code>std::as_const( object )</code></li>
</ul>
<li><a href="#7.0">VII. Sample Implemenation</a></li>
<li><a href="#8.0">VIII. Proposed Wording</a></li>
<li><a href="#9.0">IX. Further Discussion</a></li>
</ul>


<h2><a name="1.0">II. Revision History</a></h2>

<h3><a name="1.1">N4380</a></h3>


<h2><a name="2.0">II. Introduction</h2>

<p>This paper proposes a new helper function template <code>std::as_const</code>, which would
live in the <code>&lt;utility&gt;</code> header.  A simple example usage:</p>

<pre><code>#include &lt;utility&gt;
#include &lt;type_traits&gt;

void
demoUsage()
{
    std::string mutableString= "Hello World!";
    const std::string &amp;constView= std::as_const( mutableString );

    assert( &amp;constView == mutableString );
    assert( &amp;std::as_const( mutableString ) == mutableString );

    using WhatTypeIsIt= std::remove_reference_t&lt; decltype( std::as_const( mutableString ) &gt;;

    static_assert( std::is_same&lt; std::remove_const_t&lt; WhatTypeIsIt &gt;, std::string &gt;::value,
            "WhatTypeIsIt should be some kind of string." );
    static_assert( !std::is_same&lt; WhatTypeIsIt, std::string &gt;::value,
            "WhatTypeIsIt shouldn't be a mutable string." );
}
</code></pre>

<h2><a name="3.0">III. Background</h2>

<p>The C++ Language distinguishes between 'const Type' and 'Type' in ADL lookup for
selecting function overloads.  The selection of overloads can occur among
functions like:</p>

<pre><code>int processEmployees( std::vector&lt; Employee &gt; &amp;employeeList );
bool processEmployees( const std::vector&lt; Employee &gt; &amp;employeeList );
</code></pre>

<p>Oftentimes these functions should have the same behavior, but sometimes free (or
member) functions will return different types, depending upon which qualifier
(<tt>const</tt> or non-<tt>const</tt>) applies to the source type.  For example,
<code>std::vector&lt; T &gt;::begin</code> has two overloads, one returning
<code>std::vector&lt; T &gt;::iterator</code>, and the other returning
<code>std::vector&lt; T &gt;::const_iterator</code>.  For this reason <code>cbegin</code> was added to the
container member-function manifest.</p>

<h2><a name="4.0">IV. Motivation</h2>

<p>A larger project often needs to call functions, like <code>processEmployees</code>,
and selecting among specific <tt>const</tt> or non-<tt>const</tt> overloads.  Further, within
C++11 and newer contexts, passing an object for binding or perfect forwarding
can often require specifying a <tt>const</tt> qualifier applies to the actual object.
This can also be useful in specifying that a template be instantiated as
adapting to a "<tt>const</tt>" reference to an object, instead of a non-<tt>const</tt> reference.</p>

<h2><a name="5.0">V. Alternatives</h2>

<ol>
<li>Continue use the hard-to-use idiom <code>const_cast&lt; const T &amp; &gt;( object )</code></li>
<li>Use a more modern idiom <code>const_cast&lt; std::add_const&lt; decltype( object ) &gt;::type &amp; &gt;( object )</code></li>
<li>Provide a language extension, i.e.: <code>const_cast( object )</code> which is
equivalent to the above</li>
<li>Provide a modified cast form, i.e.: <code>(const) object</code> which is equivalent to
the above</li>
<li>Provide a new trailing cast-like form, i.e.:  <code>object const</code>, or <code>object const.blah</code>
or <code>object.blah const</code></li>
<li>Provide a library function, <code>as_const</code>, which this paper proposes</li>
</ol>

<h2><a name="6.0">VI. Discussion</h2>

<p>This conversion, or alternative-viewpoint, is always safe.  Following the rule
that safe and common actions shouldn't be ugly while dangerous and infrequent
actions should be hard to write, we can conclude that this addition of <tt>const</tt> is
an operation that should not be ugly and hard.  Const-cast syntax is ugly and
therefore its usage is inherently eschewed.</p>

<p>Regarding the above alternatives, each can be discussed in turn:</p>

<h3><a name="6.1"><code>const_cast&lt; const T &amp; &gt;( object )</code>:</h3>

<p>The benefits of this form are:</p>

<ul>
<li>It is portable to older compilers (e.g. C++98/03 compilers)</li>
<li>It is widely understood</li>
<li>It is not misleading</li>
</ul>

<p>The drawbacks of this form are:</p>

<ul>
<li>It is a significant amount of typing for a relatively simple operation</li>
<li>It requires the programmer to have knowledge of <code>decltype( object )</code> </li>
<li>It is phrased in a known-dangerous cast form (<code>const_cast</code>)</li>
</ul>

<h3><a name="6.2"><code>const_cast&lt; std::add_const&lt; decltype( object ) &gt;::type &amp; &gt;( object )</code>:</h3>

<p>The benefits of this form are:</p>

<ul>
<li>It is supported by C++11 and beyond</li>
<li>It requires no modifications to the C++ standard</li>
<li>It does not require the programmer to have knowledge of <code>decltype( object )</code>;
it merely requires that he use that type-deduction</li>
</ul>

<p>The drawbacks of this form are:</p>

<ul>
<li>It is not supported by C++98/03</li>
<li>It is an even more burdensome amount of typing</li>
<li>It is phrased in an incredibly ugly and hard-to-understand form</li>
<li>It is phrased using a form which requires an extra <code>typename</code> usage, when used
in a template context, due to the <code>add_const</code> metafunction</li>
<li>It is phrased in a known-dangerous cast form (<code>const_cast</code>)</li>
</ul>

<h3><a name="6.3">Extend the language with <code>const_cast( object )</code>:</h3>

<p>The benefits of this form are:</p>

<ul>
<li>It is a simple, straightforward, and understandable construct</li>
<li>It uses a presently ill-defined form</li>
</ul>

<p>The drawbacks of this form are:</p>

<ul>
<li>It is not supported by anything, at present</li>
<li>It provides an alternate, potentially confusing difference for <code>const_cast</code>,
over the other <code>_cast</code> forms currently in the core language</li>
<li>It requires a core language extension for only marginal gain</li>
<li>It is phrased in a known-dangerous cast form, which is locatable by regex</li>
</ul>

<h3><a name="6.4">Extend the language with <code>(const) object</code>:</h3>

<p>The benefits of this form are:</p>

<ul>
<li>It is a simple, straightforward, and understandable construct</li>
<li>It uses a presently ill-defined form</li>
<li>It is extremely terse</li>
</ul>

<p>The drawbacks of this form are:</p>

<ul>
<li>It is not supported by anything, at present</li>
<li>It requires a core language extension for only marginal gain</li>
<li>It is phrased in the legacy C-style casting form, which is considered (by
many) to be both outmoded and ugly</li>
</ul>

<h3><a name="6.5">Library function, <code>std::as_const( object )</code>:</h3>

<p>The benefits of this form are:</p>

<ul>
<li>It is simple, straightforward, and understandable construct</li>
<li>It requires no new core language extensions</li>
<li>It is implementable in C++98/03 terms, for those who wish to back-port the
feature</li>
<li>It is terse</li>
<li>It is not misleading</li>
<li>It does not require the programmer to know <code>decltype( object )</code></li>
<li>It follows the precedent set by <code>std::move</code> and <code>std::forward</code>, in terms of
wrapping commonly needed, but difficult to write cast expressions</li>
</ul>

<p>The drawbacks of this form are:</p>

<ul>
<li>It may not have the best name.</li>
<li>Proposed names included:
<ul>
<li><code>std::constify( object )</code></li>
<li><code>std::to_const( object )</code></li>
<li><code>std::constant( object )</code></li>
<li><code>std::view_const( object )</code></li>
<li><code>std::make_const( object )</code></li>
<li><code>std::add_const( object )</code></li>
<li><code>std::const_view( object )</code></li>
</ul></li>
</ul>

<p>In proposing <code>std::as_const( object )</code>, we feel that the name is sufficiently
terse yet descriptive.  Every other name had at least one drawback.</p>

<h2><a name="7.0">VII. Proposed Implementation</h2>

<p>In the <code>&lt;utility&gt;</code> header, the following code should work:</p>

<pre><code>// ...
// -- Assuming that the file has reverted to the global namespace --
namespace std
{
    template&lt; typename T &gt;
    inline typename std::add_const&lt; T &gt;::type &amp;
    as_const( T &amp;t ) noexcept
    {
        return t;
    }

}
// ...
</code></pre>

<h2><a name="8.0">VIII. Proposed Wording</h2>
<p>
Insert the following signature into the <tt>&lt;utility&gt;</tt> synopsis,
between 20.2.4 // forward/move, and 20.2.5 // declval:
</p>
<p><pre>
    <ins>template &lt;class T&gt; constexpr add_const_t&lt;T&gt;&amp; as_const(T&amp; t) noexcept;</ins>
    <ins>template &lt;class T&gt; void as_const(const T&amp;&amp;) = delete;</ins>
</pre></p>

<p>
Insert the following subclause between <b>20.2.4 forward/move helpers [forward]</b>, and
<b>20.2.5 Function template declval [declval]</b>:
<p>

<h3><ins>20.2.x Function template <tt>as_const</tt>   [utility.as_const]</ins></h3>
<p><pre>
    <ins>template &lt;class T&gt; constexpr add_const_t&lt;T&gt;&amp; as_const(T&amp; t) noexcept;</ins>
</pre></p>
<p><ins>
1 <i>Returns:</i>  <tt>t</tt>.
</ins></p>

<h2><a name="9.0">IX. Feature Detection Macros</h2>
<p>
For the purposes of SD-6, we recommend the feature detection macro <tt>__cpp_lib_as_const_function</tt>.
</p>

</body>
</html>
