<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Relative Paths</title>
<style>
body
{
  font-family: arial, sans-serif;
  max-width: 6.75in;
  margin: 0px auto;
  font-size: 85%;
}
 ins  {background-color: #CCFFCC; text-decoration: none;}
 del  {background-color: #FFCACA; text-decoration: none;}
 pre  {background-color: #D7EEFF; font-size: 95%; font-family: "courier new", courier, serif;}
 code {font-size: 110%; font-family: "courier new", courier, serif;}
 table {font-size: 90%;}
</style>
</head>

<body>

<table>
<tr>
  <td align="left">Doc. no.:</td>
  <td align="left">P0219R1</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">
  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y-%m-%d" startspan -->2016-06-24<!--webbot bot="Timestamp" endspan i-checksum="12400" --></td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Beman Dawes &lt;bdawes at acm dot org&gt;<br>
  Jamie Allsop &lt;jamie dot allsop at googlemail dot com&gt;<br>
  Nicolai Josuttis &lt;nico at josuttis dot de&gt;</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">Library, Filesystem</td>
</tr>
</table>

<h1>Relative Paths for Filesystem (R1)</h1>


<p><a href="#Introduction">
      Introduction</a><br>
&nbsp;&nbsp;&nbsp; <a href="#History">History</a><br>
&nbsp;&nbsp; &nbsp;<a href="#Preliminary-implementation">Preliminary implementation</a><br>
<a href="#Requirements">Requirements</a><br>
<a href="#Issues">Issues</a><br>
<a href="#Design-decisions">
      Design decisions</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-separate-relative">Provide separate lexical and 
      operational <code>relative</code> functions</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Provide-separate-proximate">
Provide 
separate lexical and operational <code>proximate</code> functions</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Add-lexical-functions">
Add lexical functions as <code>path</code> member functions</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-normal">Provide a 
<code>lexically_normal</code> member function returning a 
      normal form path</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-weakly">Provide a <code>weakly_canonical</code> operational function</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#just-work">Resolve issues in ways that &quot;just work&quot; for users</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mismatch">Specify <code>lexical relative</code> in terms 
      of <code>mismatch</code></a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Specify-op-rel-weakly">Specify operational <code>relative</code> in terms of <code>
      weakly_canonical</code></a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Specify-op-rel-lex-rel">Specify operational <code>relative</code> in terms of 
      <code>lexically
      relative</code></a><br>
&nbsp;&nbsp;&nbsp; <a href="#common_prefix-and-remove_common_prefix-functions">
Propose <code>common_prefix</code> and <code>remove_common_prefix</code> 
functions separately, as algorithms</a><br>
<a href="#Proposed-wording">Proposed wording</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Define-normal-form">
Define <i>
normal form</i></a><br>
&nbsp;&nbsp;&nbsp; <a href="#New-class-path-member-functions">
New class path member functions</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Synopsis-path">
Synopsis</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Specification-path">
Specification</a><br>
&nbsp;&nbsp;&nbsp; <a href="#operational-functions">
New operational functions</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Synopsis-ops">
Synopsis</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Specification-ops">
Specification</a><br>
<a href="#LWG-guidance-requested">LWG guidance requested</a><br>
<a href="#References">References</a></p>

<h2>
      <a name="Introduction">Introduction</a></h2>

<p>The
<a href="https://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm">
Boost Filesystem library</a> has had user requests for a  relative path function for 
more than ten years. For the <i>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf">File System TS</a></i>, the issue was 
raised as LWG 2611, PDTS 
comment GB-1, and resolved as <em>NAD Future</em>. A proposed solution,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html">
P0011R0, <i>
Additions to Filesystem supporting Relative Paths</i></a>, is currently before the committee.</p>

<p>
      The requested functionality seems simple - given two paths with a common 
      prefix, return the non-common suffix portion of one of the paths such that 
      it is relative to the other path.</p>

<p>
      In terms of the Filesystem library,</p>

<blockquote>
  <pre>path p(&quot;/a/b/c&quot;);
path base(&quot;/a/b&quot;);
path rel = relative(p, base);  // the requested function
cout &lt;&lt; rel &lt;&lt; endl;           // outputs &quot;c&quot;
assert(absolute(rel, base) == p);</pre>
</blockquote>
<p>If that was all there was to it,  Filesystem would have had a
<code>relative</code> function years ago. Other libraries supply such a 
function, such as
<a href="https://docs.python.org/2/library/os.path.html#os.path.relpath">
Python&#39;s os.path.relpath</a>, albeit with simplistic semantics.</p>
<p>The problem with simplistic semantics:</p>
<ul>
  <li>Clashing requirements</li>
  <li>Symlinks</li>
  <li>Directory placeholders (<i>dot</i>,
<i>dot-dot</i>)</li>
  <li>User-expectations</li>
  <li>Corner cases.</li>
</ul>
<p>In previous discussions, committee members have made it clear that they do 
not want an overly simplistic solution.</p>
<h3><a name="History">History</a></h3>
<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html">
P0011R0, <i>
Additions to Filesystem supporting Relative Paths</i></a> by Jamie Allsop and Nico Josuttis 
is what broke the &quot;relative&quot; logjam. Much of what follows is based directly on 
that proposal. The <code>weakly_canonical</code> function and 
details of the semantic specifications such as use of <code>mismatch</code> 
were introduced by Beman Dawes.</p>
<h3><a name="Preliminary-implementation">Implementation</a> experience</h3>
<p>
<a href="https://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm">
Boost Filesystem 1.60.0</a> shipped a preliminary implementation of this 
proposal in December, 2015.</p>
<h2><a name="Requirements">Requirements</a></h2>
<b><a name="Requirement-1">Requirement 1</a>:</b> Some uses require symlinks be followed; i.e. the path must be resolved in 
  the actual file system.<p><b><a name="Requirement-2">Requirement 2</a>: </b>Some uses require symlinks not be followed; i.e. the path must not be 
  resolved in the actual file system.</p>
<b><a name="Requirement-3">Requirement 3</a>: </b>Some uses require removing redundant current directory (<i>dot</i>) 
  or parent directory (<i>dot-dot</i>) placeholders.<p><b>
<a name="Requirement-4">Requirement 4</a>: </b>Some uses do not require removing redundant current directory (<i>dot</i>) 
  or parent directory (<i>dot-dot</i>) placeholders since the path is known to 
be 
already in normal form.</p>
<h2><a name="Issues">Issues</a></h2>
<p><b><a name="Issue-1">Issue 1</a>:</b> What happens if <code>p</code> 
and <code>base</code> are themselves relative?</p>
<b><a name="Issue-2">Issue 2</a>:</b> What happens if there is no common prefix? Is this an error, the whole of
  <code>p</code> is relative to <code>base</code>, or something else?<p><b>
<a name="Issue-3">Issue 3</a>:</b> What happens if <code>p</code>, <code>base</code>, or both are empty?</p>
<b><a name="Issue-4">Issue 4</a>:</b> What happens if <code>p</code> and <code>base</code> are the same?<p>
<b><a name="Issue-5">Issue 5</a>:</b> How is the &quot;common prefix&quot; determined?</p>
<b><a name="Issue-6">Issue 6</a>:</b> What happens if portions of <code>p</code> or <code>base</code> exist but 
  the entire path does not exist and yet symlinks need to be followed?<p><b>
<a name="Issue-7">Issue 7</a>:</b> What happens when a symlink in the existing portion of a path is affected 
  by a directory (<i>dot-dot</i>) placeholder in a later non-existent portion of 
  the path?</p>
<p><b><a name="Issue-8">Issue 8</a>:</b> Overly complex semantics (and thus 
specifications) in preliminary designs made reasoning about uses difficult.</p>
<p><b><a name="Issue-9">Issue 9</a>: </b>Some uses never have redundant current directory (<i>dot</i>) 
  or parent directory (<i>dot-dot</i>) placeholders, so a removal operation 
  would be an unnecessary expense although otherwise harmless.</p>

<h2>
      <a name="Design-decisions">Design decisions</a></h2>

<h4>
      <a name="Provide-separate-relative">Provide separate</a> lexical and 
      operational <code>relative</code> functions</h4>

<p align="left">
      Resolves the conflict between <a href="#Requirement-1">requirement 1</a> 
      and <a href="#Requirement-2">requirement 2</a> and ensures both 
      requirements are met.</p>

<p>
      A purely lexical function is needed by users working with directory 
      hierarchies that do not actually exist.</p>

<p>
      An operational function that queries the current file system for existence 
      and follows symlinks is needed by users working with actual existing 
      directory hierarchies.</p>

<h4>
      <a name="Provide-separate-proximate">Provide separate</a> lexical and operational
      <code>proximate</code> functions</h4>

<p>
      Although not the only possibility, a likely fallback when the relative 
      functions cannot find a relative path is to return the path being made relative. As 
      a convenience, the <code>proximate</code> functions do just that.</p>

<h4>
      <a name="Add-lexical-functions">Add lexical functions as 
      <code>path</code> member functions</a></h4>

<p>
      This is the Filesystem library convention, but it is controversial. See
      <a href="#LWG-guidance-requested">LWG guidance requested</a>.</p>

<h4>
      <a name="Provide-normal">Provide</a><b> </b>a <code>
      <a href="#normal">lexically_normal</a></code> member function returning a 
      <a href="#normal-form">normal form</a> path</h4>

<p>
      Enables resolution of <a href="#Requirement-3">requirement 3</a> and
      <a href="#Requirement-4">requirement 4</a> in a way consistent with
      <a href="#Issue-9">issue 9</a>. Is a contributor to the resolution of
      <a href="#Issue-8">issue 8</a>.</p>

<p>
      &quot;Normalization&quot; is the process of removing redundant current directory (<i>dot</i>) 
      , parent 
      directory (<i>dot-dot</i>), and directory separator elements.</p>

<p>
      Normalization is a byproduct the current <code>canonical</code> function. 
      But for the path returned by the 
      proposed <code><a href="#weakly_canonical">weakly_canonical</a></code> function, 
      only any leading canonic portion is in canonical form. So any trailing 
      portion of the returned path has not been normalized.</p>

<p>
      Boost.filesystem has a  non-const normalization function that was 
      deprecated because it 
      modifies the path, and that sometimes caused user confusion. We believe that a 
      const function returning a path 
      is a better solution.</p>

<h4>
      <a name="Provide-weakly">Provide</a><b> </b>a <code><a href="#weakly_canonical">weakly_canonical</a></code> operational function</h4>

<p>
      Resolves <a href="#Issue-6">issue 6</a>, <a href="#Issue-7">issue 7</a>,
      <a href="#Issue-9">issue 9</a>, and is a contributor to the resolution of
      <a href="#Issue-8">issue 8</a>.</p>

<p>
      The operational function
      <code>weakly_canonical(p)</code> returns a path composed of <code>
      canonical(x)/y</code>, where <code>x</code> is a path composed of the 
      longest leading sequence of elements in <code>p</code> that exist, and
      <code>y</code> is a path composed of the remaining trailing non-existent elements of
      <code>p</code> if any. &quot;<code>weakly</code>&quot; refers to weakened existence 
      requirements compared to the existing canonical function.</p>

<ul>
  <li>Having <code>weakly_canonical</code> as a separate function, and then 
  specifying the processing of operational <code>relative</code> arguments in 
  terms of calls to <code>weakly_canonical</code> makes it much easier to 
  specify the operational <code>relative</code> function and reason about it. 
  The difficulty of reasoning about operational <code>relative</code> 
  semantics before the invention of <code>weakly_canonical</code> was what led to its 
  initial development.</li>
  <li>Having <code>weakly_canonical</code> as a separate function also allows 
  use in other contexts.</li>
  <li>Specifying the return be in <a href="#normal-form">normal form</a> is an 
  engineering trade-off to resolve <a href="#Issue-7">issue 7</a> in a way that 
  just works for most use cases.</li>
  <li>Specifying normative encouragement to not perform unneeded normalization 
  is a reasonable resolution for <a href="#Issue-9">issue 9</a>.</li>
</ul>

<h4>
      Resolve issues in ways that &quot;<a name="just-work">just work</a>&quot; for users</h4>

<p>
      Resolves issues <a href="#Issue-1">1</a>, <a href="#Issue-2">2</a>,
      <a href="#Issue-3">3</a>, <a href="#Issue-4">4</a>, <a href="#Issue-7">6</a>, 
      and <a href="#Issue-7">7</a>. Is a contributor to the resolution of
      <a href="#Issue-8">issue 8</a>.</p>

<p>
      The &quot;just works&quot; approach was suggested by Jamie Allsop. It is implemented 
      by specifying a reasonable return value for all of the &quot;What happens 
      if...&quot; corner case issues, rather that treating them as hard errors 
      requiring an exception or error code.</p>

<h4>
      Specify <a href="#lex-proximate"><code>lexically relative</code></a> in terms 
      of <code>std::<a name="mismatch">mismatch</a></code></h4>

<p>
      Resolves <a href="#Issue-5">issue 5</a>. Is a contributor to the 
      resolution of <a href="#Issue-8">issue 8</a>.</p>

<h4>
      <a name="Specify-op-rel-weakly">Specify</a> operational <code>
      <a href="#op-relative">relative</a></code> in terms of <code>
      <a href="#weakly_canonical">weakly_canonical</a></code></h4>

<p>
      Is a contributor to the resolution of <a href="#Issue-8">issue 8</a>.</p>

<ul>
  <li>Covers a wide range of uses cases since a single function works for 
  existing, non-existing, and partially existing paths.</li>
  <li>Works correctly for partially existing paths that contain symlinks.</li>
</ul>

<h4>
      <a name="Specify-op-rel-lex-rel">Specify</a> operational <code>
      <a href="#op-relative">relative</a></code> in terms of 
      <a href="#lex-proximate"><code>lexically
      relative</code></a></h4>

<p>
      Is a contributor to the resolution of <a href="#Issue-5">issue 5</a> and
      <a href="#Issue-8">issue 8</a>.</p>

<p>
      If would be confusing to users and difficult to specify correctly if the 
      two functions had differing semantics:</p>
<ul>
  <li>When either or both paths are empty.</li>
  <li>When all elements of the two paths match exactly.</li>
  <li>Because different matching algorithms were used.</li>
  <li>Because although the same matching algorithm was used, it was applied in different ways.</li>
</ul>

<p>
      These problems are avoided by specifying operational <code>relative</code> 
      in terms of lexical <code>relative</code> after preparatory 
      calls to operational functions.</p>

<h4>
      Propose <a name="common_prefix-and-remove_common_prefix-functions"> <code>common_prefix</code> 
      and <code>remove_common_prefix</code> functions</a> separately, as 
      algorithms</h4>

<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html">P0011R0</a> proposed <code>common_prefix</code> and <code>
      remove_common_prefix</code> functions. In subsequent discussions between 
Allsop, Dawes, and Josuttis, it became clear that these functions are generic 
algorithms and are generally useful, but are not actually required for purposes 
of this filesystem proposal. </p>

<p>
      So these two functions are not a part of this proposal. Instead, a 
      separate proposal will suggest adding these to clause 24, Algorithms 
      library.</p>

<h2><a name="Proposed-wording">Proposed wording</a></h2>

<p><span style="background-color: #DBDBDB"><i>Add&nbsp; a new definition to 
27.10.4 Terms and definitions [fs.definitions]:</i></span></p>

<h4>27.10.4.n<br>
<a name="Define-normal-form">normal form</a> [fs.def.normal.form]</h4>

<p>A path in <b><i><a name="normal-form">normal form</a></i></b> has no 
redundant current directory (<i>dot</i>) elements, no redundant parent directory (<i>dot-dot</i>) 
elements, and no redundant <i>directory-separator</i>s. The normal form for an empty path is an empty path. The normal form 
for a path ending in a <i>directory-separator</i> that is not the root directory 
has a current directory (<i>dot</i>) element appended.</p>

<p>[<i>Note:</i> The rule that appends a current directory (<i>dot</i>) element 
supports operating systems like OpenVMS that use different syntax for directory 
names and regular-file names. —<i>end note</i>]</p>

<p><span style="background-color: #DBDBDB"><i>Add a new sub-section to the 
synopsis in 27.10.8 Class path [class.path] after // 27.10.8.4.10, query:</i></span></p>


<pre>// [path.gen] Generation
path lexically_normal() const;
path lexically_relative(const path&amp; base) const;
path lexically_proximate(const path&amp; base) const;</pre>


<p>

<span style="background-color: #DBDBDB; font-style:italic">Add a new sub-section 
after // 27.10.8.4.10 [path.query]:</span> </p>
<h4>27.10.8.4.11 <code>path</code> generation [path.gen]</h4>


<pre>path <a name="lex-normal">lexically_normal</a>() const;</pre>
<blockquote>
<p><i>Returns:</i> <code>*this</code> in <a href="#normal-form">normal form</a>.</p>
<p>[<i>Example:</i></p>
<p><code>assert(path(&quot;foo/./bar/..&quot;).lexically_normal() == &quot;foo&quot;);<br>
assert(path(&quot;foo/.///bar/../&quot;).lexically_normal() == &quot;foo/.&quot;);</code></p>
<p>The above assertions will succeed. The second example ends with a current 
directory (<i>dot</i>) element appended to support operating systems that use 
different syntax for directory names and regular-file names. </p>
<p>On Windows, the 
returned path&#39;s <i>directory-separator</i> characters will be backslashes rather than slashes, but that 
does not affect <code>path</code> equality.<i> —end example</i>]</p>
</blockquote>

<pre>path <a name="lex-relative">lexically_relative</a>(const path&amp; base) const;</pre>
  <blockquote>
  <p>Returns <code>*this</code> made relative to <code>base</code>. 
  Does not resolve symlinks. Does not first normalize <code>*this</code> or <code>base</code>.</p>

  <p><i>Effects:</i> </p>
  
  <p>Using&nbsp; <code>operator==</code> to determine if elements match, 
  determines the first mismatched element of
  <code>*this</code> and <code>base</code> using <code>mismatch(begin(), end(), base.begin(), base.end())</code>.</p>
  
  <p>Then:</p>
  
  <ul>
    <li>
  return
  <code>path()</code> if the first mismatched element of <code>*this</code> is equal to <code>
  begin()</code> or the first mismatched element 
  of <code>base</code> is equal to <code>base.begin()</code>, or<br>&nbsp;
    </li>
    <li>
  return
  <code>path(&quot;.&quot;)</code> if the first mismatched element of <code>
  *this</code> is equal to <code>
  end()</code> and the first mismatched element 
  of <code>base</code> is equal to <code>base.end()</code>, or<br>&nbsp;
    </li>
    <li>return an object of class <code>path</code> composed via application of <code>
    operator/= (path(&quot;..&quot;))</code> for each element in the half-open 
    range [first 
    mismatched element of <code>base</code>, <code>base.end()</code>), and then 
    application of <code>operator/=</code> for each element in the half-open 
    range 
    [first mismatched element of <code>*this</code>, <code>end()</code>).
    </li>
</ul>
  
<p>[<i>Example:</i></p>
<p><code>assert(path(&quot;/a/d&quot;).lexically_relative(&quot;/a/b/c&quot;) ==  &quot;../../d&quot;);<br>
assert(path(&quot;/a/b/c&quot;).lexically_relative(&quot;/a/d&quot;) ==  &quot;../b/c&quot;);<br>
assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a&quot;) == &quot;b/c&quot;);<br>
assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a/b/c/x/y&quot;) ==  &quot;../..&quot;);<br>
assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a/b/c&quot;) ==  &quot;.&quot;);<br>
assert(path(&quot;a/b&quot;).lexically_relative(&quot;c/d&quot;) ==  &quot;&quot;);</code></p>
<p>The above assertions will succeed.<i> </i>On Windows, the 
returned path&#39;s <i>directory-separator</i>s will be backslashes rather than 
forward slashes, but that 
does not affect <code>path</code> equality.<i> —end example</i>]</p>
  
  <p>[<i>Note:</i> If symlink following semantics are desired, use the  operational function <code>
  <a href="#op-proximate">relative</a>()</code>&nbsp; <i>—end note</i>]</p>
  
  <p>[<i>Note:</i> If <a href="#normal">normalization</a> is needed to ensure 
  consistent matching of elements, apply <code><a href="#normal">lexically_normal()</a></code> 
  to <code>*this</code>, <code>base</code>, or both. <i>—end note</i>]</p>
  
</blockquote>


<pre>path <a name="lex-proximate">lexically_proximate</a>(const path&amp; base) const;</pre>

  <blockquote>
  
  <p><i>Returns:</i> If the value of <code>lexically_relative(base)</code> is 
  not an empty path, return it. Otherwise return <code>*this</code>.</p>
  
  <p>[<i>Note:</i> If symlink following semantics are desired, use the  operational function
  <code><a href="#op-proximate">proximate()</a></code>&nbsp; <i>—end note</i>]</p>
  
  <p>[<i>Note:</i> If <a href="#normal">normalization</a> is needed to ensure 
  consistent matching of elements, apply <code><a href="#normal">lexically_normal()</a></code> 
  to <code>*this</code>, <code>base</code>, or both. <i>—end note</i>]</p>
  
</blockquote>


<p><span style="background-color: #DBDBDB"><i>Add the following new </i>
filesystem operational functions<i> to 27.10.6 Header &lt;filesystem&gt; synopsis [fs.filesystem.syn]. 
Please maintain the alphabetic ordering of operational functions:</i></span></p>


<pre>...
path proximate(const path&amp; p, error_code&amp; ec);
path proximate(const path&amp; p, const path&amp; base=current_path());
path proximate(const path&amp; p, const path&amp; base, error_code&amp; ec);
...
path relative(const path&amp; p, error_code&amp; ec);
path relative(const path&amp; p, const path&amp; base=current_path());
path relative(const path&amp; p, const path&amp; base, error_code&amp; ec);
...
path weakly_canonical(const path&amp; p);
path weakly_canonical(const path&amp; p, error_code&amp; ec);
...
</pre>
<p><span style="background-color: #DBDBDB"><i>Add the following new filesystem 
operational functions to 27.10.15 Filesystem operation functions [fs.op.funcs]. 
Please maintain the alphabetic ordering of operational functions:</i></span></p>

<h4>27.10.15.n Proximate[fs.op.proximate]</h4>

<pre>path <a name="op-proximate">proximate</a>(const path&amp; p, error_code&amp; ec);</pre>
<blockquote>
<p><i>Returns:</i> <code>proximate(p, current_path(), ec)</code>.</p>
  <p><i>Throws:</i>&nbsp; As specified in Error reporting ([fs.err.report]).</p>
  </blockquote>
<pre>path proximate(const path&amp; p, const path&amp; base=current_path());
path proximate(const path&amp; p, const path&amp; base, error_code&amp; ec);</pre>
<blockquote>

<p><i>Returns:</i> For the first form, <code><a href="#weakly_canonical">weakly_canonical</a>(p).<a href="#lex-proximate">lexically_proximate</a>(<a href="#weakly_canonical">weakly_canonical</a>(base))</code>. 
For the second form, <code><a href="#weakly_canonical">weakly_canonical</a>(p, 
ec).<a href="#lex-proximate">lexically_proximate</a>(<a href="#weakly_canonical">weakly_canonical</a>(base, ec))</code>&nbsp; except <code>path()</code> 
at the first error occurrence, if any.</p>
  <p><i>Throws:</i> As specified in Error reporting ([fs.err.report]).</p>
</blockquote>

 
<h4>27.10.15.n Relative [fs.op.relative]</h4>
 
<pre>path <a name="op-relative">relative</a>(const path&amp; p, error_code&amp; ec);</pre>
<blockquote>
<p><i>Returns:</i> <code>relative(p, current_path(), ec)</code>.</p>
  <p><i>Throws:</i>&nbsp; As specified in Error reporting([fs.err.report]).</p>
  
  </blockquote>
  
 
<pre>path relative(const path&amp; p, const path&amp; base=current_path());
path relative(const path&amp; p, const path&amp; base, error_code&amp; ec);</pre>
<blockquote>
  <p>Returns <code>p</code> made relative to <code>
  base</code>.  
  Resolves symlinks and normalizes both <code>p</code> and <code>base</code> 
  before other processing.</p>

<p><i>Returns: </i>For the first form, <code><a href="#weakly_canonical">weakly_canonical</a>(p).<a href="#lex-relative">lexically_relative</a>(<a href="#weakly_canonical">weakly_canonical</a>(base))</code>. 
For the second form, <code><a href="#weakly_canonical">weakly_canonical</a>(p, 
ec).<a href="#lex-relative">lexically_relative</a>(<a href="#weakly_canonical">weakly_canonical</a>(base, 
ec))</code> except <code>path()</code> at the first error occurrence, if any.</p>
  <p><i>Throws:</i> As specified in Error reporting ([fs.err.report]).</p>
</blockquote>

<h4>27.10.15.n Weakly Canonical [fs.op.weakly_canonical]</h4>

<pre>path <a name="weakly_canonical">weakly_canonical</a>(const path&amp; p);
path weakly_canonical(const path&amp; p, error_code&amp; ec);</pre>
<blockquote>
Returns <code>p</code> with symlinks resolved and the result 
normalized.<p dir="ltr">
<i>Effects: </i>Using the <code>status(p)</code> or <code>status(p, ec)</code>, 
respectively to determine existence, 
return a path composed by <code>operator/=</code>&nbsp; from the result of calling 
<code>canonical()</code> without a <code>base</code> argument and with a path 
argument composed of the leading elements of <code>p</code> that exist, if any, 
followed by the elements of <code>p</code> that do not exist, if any. For the 
first form, <code>canonical()</code> is called without an <code>error_code</code> 
argument. For the second form, <code>canonical()</code> is called with <code>ec</code> 
as an <code>error_code</code> argument, and return <code>path()</code> at the 
first error occurrence, if any.</p>
<p><i>Postconditions:</i> The returned path is in <a href="#normal">normal form</a>.</p>
<p><i>Remarks:</i> Implementations are encouraged to avoid unnecessary 
normalization such as when <code>canonical()</code> has already been called on the 
entirety of <code>p</code>.</p>
<p><i>Throws:</i>&nbsp; As specified in Error reporting ([fs.err.report]).</p>
</blockquote>
  
 
<blockquote>
  <p align="center">

<span style="background-color: #DBDBDB"><i>-- end proposed wording --</i></span> </p>
</blockquote>

<hr>

  <h2><a name="LWG-guidance-requested">LWG guidance requested</a></h2>

<p>
      The Filesystem library is unusual in that it has several functions with 
      both lexical (i.e. cheap) and operational (i.e. expensive due to file 
      system access) forms with differing semantics. It is important that users 
      choose the form that meets their application&#39;s specific needs. The library 
      has always made the distinction via the convention of lexical functions 
      being members of class <code>path</code>, while operational functions are 
      non-member functions. The current wording of this proposal follows the 
      path member function convention for the new lexical function. The lexical functions proposed here also use the 
      name prefix <code>lexically_</code> to drive home the distinction.</p>

<p>
      For the contrary argument, see Sutter and Alexandrescu, <i>C++ Coding Standards</i>, 44: 
      &quot;Prefer writing nonmember nonfriend functions&quot;, and Meyers, <i>Effective C++ Third Edition</i>, 23: 
      &quot;Prefer non-member non-friend functions to member functions.&quot;</p>

  <p><span style="background-color: #DBDBDB"><i>At the Oulu meeting the LWG 
  indicated a strong preference for the member / non-member convention as 
  proposed and the 
  naming as proposed.</i></span> </p>

  <h2><a name="References">References</a></h2>

<p>[<a name="1">1</a>] Beman Dawes,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf">
N4100, Programming Languages — C++ — File System Technical Specification</a>, 
2014.<br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf" class="uri">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf</a></p>
<p>[<a name="2">2</a>] Beman Dawes, others,
<a href="http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm">
Boost Filesystem Library, V3</a>, 2015.<br>
<a href="https://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm" class="uri">
https://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm</a></p>
<p>[<a name="3">3</a>] Jamie Allsop, Nicolai Josuttis,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html">
P0011R0, Additions to Filesystem supporting Relative Paths</a>, 2015.<br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html" class="uri">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0011r0.html</a></p>
<p>[4] Python.org,
<a href="https://docs.python.org/2/library/os.path.html#os.path.relpath">
Function os.path.relpath documentation</a>,<br>
<a href="https://docs.python.org/2/library/os.path.html#os.path.relpath">
https://docs.python.org/2/library/os.path.html#os.path.relpath</a></p>

<hr>

</body>

</html>