<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="give-stdstring-a-non-const-.data-member-function.">Give 'std::string' a non-const '.data()' member function.</h1>
<ul>
<li>Document number: P0272R1</li>
<li>Date: 2016-03-04</li>
<li>Reply-to: David Sankel <script type="text/javascript">
<!--
h='&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#46;&#x63;&#x6f;&#x6d;';a='&#64;';n='&#100;&#x61;&#118;&#x69;&#100;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
// -->
</script><noscript>&#100;&#x61;&#118;&#x69;&#100;&#32;&#x61;&#116;&#32;&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#x63;&#x6f;&#x6d;</noscript></li>
<li>Audience: Library Evolution</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>Is <code>std::string</code>'s lack of a non-const <code>.data()</code> member function an oversight or an intentional design based on pre-C++11 <code>std::string</code> semantics? In either case, this lack of functionality tempts developers to use unsafe alternatives in several legitimate scenarios. This paper argues for the addition of a non-const <code>.data()</code> member function for <code>std::string</code> to improve uniformity in the standard library and to help C++ developers write correct code.</p>
<h2 id="changes">Changes</h2>
<p>P0272R1 added a node for Annex C.4 wrt. the implications of this change and fixed minor formatting issues.</p>
<h2 id="introduction">Introduction</h2>
<p>This paper brings to discussion an issue that was originally brought forward in <a href="http://wg21.cmeerw.net/lwg/issue2391">LWG issue 2391</a> by Michael Bradshaw. It was moved to a LEWG issue in 2015 and hasn't been looked at since. This is being elevated to a paper in the hopes that it will finally be addressed.</p>
<h2 id="use-cases">Use Cases</h2>
<p>C libraries occasionally include routines that have <code>char *</code> parameters. One example is the <code>lpCommandLine</code> parameter of the <code>CreateProcess</code> function in the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx">Windows API</a>. Because the <code>data()</code> member of <code>std::string</code> is const, it cannot be used to make <code>std::string</code> objects work with the <code>lpCommandLine</code> parameter. Developers are tempted to use <code>.front()</code> instead, as in the following example.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">std::string programName;

<span class="co">// ...</span>

<span class="kw">if</span>( CreateProcess( NULL, &amp;programName.front(), <span class="co">/* etc. */</span> ) ) {
  <span class="co">// etc.</span>
} <span class="kw">else</span> {
  <span class="co">// handle error</span>
}</code></pre></div>
<p>Note that when <code>programName</code> is empty, the <code>programName.front()</code> expression causes undefined behavior. A temporary empty C-string fixes the bug.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">std::string programName;

<span class="co">// ...</span>

<span class="kw">if</span>( !programName.empty() ) {

  <span class="dt">char</span> emptyString[] = {<span class="st">&#39;</span><span class="ch">\0</span><span class="st">&#39;</span>};

  <span class="kw">if</span>( CreateProcess( NULL, programName.empty() ? emptyString : &amp;programName.front(), <span class="co">/* etc. */</span> ) ) {
    <span class="co">// etc.</span>
  } <span class="kw">else</span> {
    <span class="co">// handle error</span>
  }
}</code></pre></div>
<p>If there were a non-const <code>.data()</code> member, as there is with <code>std::vector</code>, the correct code would be straightforward.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">std::string programName;

<span class="co">// ...</span>

<span class="kw">if</span>( !programName.empty() ) {

  <span class="dt">char</span> emptyString[] = {<span class="st">&#39;</span><span class="ch">\0</span><span class="st">&#39;</span>};

  <span class="kw">if</span>( CreateProcess( NULL, programName.data(), <span class="co">/* etc. */</span> ) ) {
    <span class="co">// etc.</span>
  } <span class="kw">else</span> {
    <span class="co">// handle error</span>
  }
}</code></pre></div>
<p>A non-const <code>.data()</code> <code>std::string</code> member function is also convenient when calling a C-library function that doesn't have const qualification on its C-string parameters. This is common in older codes and those that need to be portable with older C compilers.</p>
<h2 id="wording">Wording</h2>
<p>The wording here was taken directly from <a href="http://wg21.cmeerw.net/lwg/issue2391">LWG issue 2391</a>.</p>
<ol style="list-style-type: decimal">
<li><p>Change class template basic_string synopsis, [basic.string], as indicated:</p>
<pre>
  namespace std {
    template&lt;class charT, class traits = char_traits&lt;charT&gt;,
    class Allocator = allocator&lt;charT&gt; &gt;
    class basic_string {
    public:
      […]
      <i>// 21.4.7, string operations:</i>
      const charT* c_str() const noexcept;
      const charT* data() const noexcept;
      <ins>charT* data() noexcept;</ins>
      allocator_type get_allocator() const noexcept;
      […]
    };
  }
  </pre></li>
<li><p>Add the following sequence of paragraphs following [string.accessors] p3, as indicated:</p>
<pre>
  <ins>charT* data() noexcept;</ins>
  </pre>
<blockquote>
<p>
<ins><i>Returns:</i> A pointer <code>p</code> such that <code>p + i == &amp;operator[](i)</code> for each <code>i</code> in <code>[0,size()]</code>.
<p />
<ins><i>Complexity:</i> Constant time.
<p></p>
<ins><i>Requires:</i> The program shall not alter the value stored at <code>p + size()</code>.
</p>
<p></blockquotes></p></li>
<li><p>Add the following section after Annex C.4.3</p>
<ins>
<h2>
C.4.4 Clause 21: strings library [diff.cpp14.strings]
</h2>
21.4
<p>
<b>Change:</b> const <code>.data()</code> member added.
</p>
<p>
<b>Rationale:</b> The lack of a const <code>.data()</code> differed from the similar member of <code>std::vector</code>. This change regularizes behavior for this International Standard.
</p>
<p>
<b>Effect on original feature:</b> Overloaded functions which have differing code paths for <code>char*</code> and <code>const char*</code> arguments will execute differently when called with a non-const string's <code>.data()</code> member in this International Standard.
</p>
<p></ins></p></li>
</ol>
</body>
</html>
