<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2665: remove_filename() post condition is incorrect</title>
<meta property="og:title" content="Issue 2665: remove_filename() post condition is incorrect">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2665.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#Resolved">Resolved</a> status.</em></p>
<h3 id="2665"><a href="lwg-defects.html#2665">2665</a>. <code>remove_filename()</code> post condition is incorrect</h3>
<p><b>Section:</b> 31.12.6.5.5 <a href="https://wg21.link/fs.path.modifiers">[fs.path.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Eric Fiselier <b>Opened:</b> 2014-06-07 <b>Last modified:</b> 2017-07-17</p>
<p><b>Priority: </b>1
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
  <code>remove_filename()</code> specifies <code>!has_filename()</code> as the post condition.
This post condition is not correct. For example the path <code>"/foo"</code>
has a filename of <code>"foo"</code>. If we remove the filename we get <code>"/"</code>,
and <code>"/"</code> has a filename of <code>"/"</code>.</p>

<p><i>[2014-06-08 Beman supplies an <i>Effects:</i> element.]</i></p>


<p><i>[2014-06-17 Rapperswil LWG will investigate issue at a subsequent meeting.]</i></p>


<p><i>[<b>2016-04  Issue updated to address the C++ Working Paper. Previously addressed File System TS</b>]</i></p>
 

<p><i>[2016-04, Issues Telecon]</i></p>

<p>
There was concern that the effects wording is not right.  Jonathan provided updated wording.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
  <pre>
    path&amp; <a name="path-remove_filename">remove_filename</a>();
  </pre>
  <blockquote>
    <p>
      <del><i>Postcondition:</i> <code>!has_filename()</code>.</del>
    </p>
    <p>
    <ins>
      <i>Effects:</i> <code>*this = parent_path()</code>, except that if <code>parent_path() == root_path()</code>, <code>clear()</code>.
    </ins>
    </p>
    <p>
      <i>Returns: </i> <code>*this</code>.
    </p>
    <p>
      [<i>Example:</i>
    </p>
    <blockquote>
      <pre>
        <code>std::cout &lt;&lt; path(&quot;/foo&quot;).remove_filename();</code>  // outputs &quot;<code>/</code>&quot;
        std::cout &lt;&lt; path(&quot;/&quot;).<code>remove_</code>filename();     // outputs &quot;&quot;
      </pre>
    </blockquote>
    <p>
      <i>&mdash;end example</i>]
    </p>
  </blockquote>
</blockquote>

<p><i>[2016-08 Chicago]</i></p>

<p>Wed AM: Move to Tentatively Ready</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<pre>
  path&amp; <a name="path-remove_filename">remove_filename</a>();
</pre>
<blockquote>
  <p>
    <del>Postcondition: !has_filename().</del>
  </p>
  <p>
    <ins>Effects: If <code>*this == root_path()</code>, then <code>clear()</code>. Otherwise, <code>*this = parent_path()</code>.</ins>
  </p>
  <p>
    <i>Returns: </i> <code>*this</code>.
  </p>
  <p>
    [<i>Example:</i><br/>
  <blockquote>
    <pre>
      <code>std::cout &lt;&lt; path(&quot;/foo&quot;).remove_filename();</code>  // outputs &quot;<code>/</code>&quot;
      std::cout &lt;&lt; path(&quot;/&quot;).<code>remove_</code>filename();     // outputs &quot;&quot;
    </pre>
  </blockquote><br/>
    <i>&mdash;end example</i>]
  </p>
  </blockquote>
</blockquote>

<p><i>[2016-10-16, Eric reopens and provides improved wording]</i></p>

<p>
The suggested PR is incorrect. <code>root_path()</code> removes redundant directory separators.
<p/>
Therefore the condition <code>*this == root_path()</code> will fail for <code>"//foo///"</code> because <code>root_path()</code> 
returns <code>"//foo/"</code>. However using <code>path::compare</code> instead would solve this problem.
</p>

<p><i>[2016-11-21, Beman comments]</i></p>

<p>
This issue is closely related to CD NB comments US 25, US 37, US 51, US 52, US 53, US 54, and US 60. The Filesystem 
SG in Issaquah recommended that these all be handled together, as they all revolve around the exact meaning of 
"filename" and path decomposition.
</p>

<p><i>[2017-07-14, Davis Herring comments]</i></p>

<p>
Changes in <a href="https://wg21.link/p0492r2">P0492R2</a> changed <code>remove_filename()</code> and <code>has_filename()</code> 
in such a fashion that the postcondition is now satisfied. (In the example in the issue description, <code>"/foo"</code> 
does gets mapped to <code>"/"</code>, but <code>path("/").has_filename()</code> is <code>false</code>.)
</p>

<p><i>[2017-07, Toronto Thursday night issues processing]</i></p>

<p>This was resolved by the adoption of <a href="https://wg21.link/p0492r2">P0492R2</a>.</p>


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

<ol>
<li><p>Modify 31.12.6.5.5 <a href="https://wg21.link/fs.path.modifiers">[fs.path.modifiers]</a> as indicated:</p>

<blockquote>
<pre>
path&amp; remove_filename();
</pre>
<blockquote>
<p>
-5- <i><del>Postcondition</del><ins>Effects</ins>:</i> <del><code>!has_filename()</code></del><ins>If 
<code>this-&gt;compare(root_path()) == 0</code>, then <code>clear()</code>. Otherwise, <code>*this = parent_path()</code>.</ins>.
<p/>
-6- <i>Returns:</i> <code>*this</code>.
<p/>
-7- [<i>Example:</i>
</p>
<blockquote>
<pre>
std::cout &lt;&lt; path("/foo").remove_filename(); // outputs "/"
std::cout &lt;&lt; path("/").remove_filename(); // outputs ""
</pre>
</blockquote>
<p>
&mdash; <i>end example</i>]
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
