• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2
3<head>
4<meta http-equiv="Content-Language" content="en-us">
5<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
6<meta name="ProgId" content="FrontPage.Editor.Document">
7<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
8<title>Filesystem Relative Proposal</title>
9<link href="styles.css" rel="stylesheet">
10</head>
11
12<body>
13
14<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
15  <tr>
16    <td width="277">
17<a href="../../../index.htm">
18<img src="../../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="300" height="86" border="0"></a></td>
19    <td align="middle">
20    <font size="7">Filesystem Relative<br>
21    Draft Proposal</font>
22    </td>
23  </tr>
24</table>
25
26<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse"
27 bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
28  <tr>
29    <td><a href="index.htm">Home</a> &nbsp;&nbsp;
30    <a href="tutorial.html">Tutorial</a> &nbsp;&nbsp;
31    <a href="reference.html">Reference</a> &nbsp;&nbsp;
32    <a href="faq.htm">FAQ</a> &nbsp;&nbsp;
33    <a href="release_history.html">Releases</a> &nbsp;&nbsp;
34    <a href="portability_guide.htm">Portability</a> &nbsp;&nbsp;
35    <a href="v3.html">V3 Intro</a> &nbsp;&nbsp;
36    <a href="v3_design.html">V3 Design</a> &nbsp;&nbsp;
37    <a href="deprecated.html">Deprecated</a> &nbsp;&nbsp;
38    <a href="issue_reporting.html">Bug Reports </a>&nbsp;&nbsp;
39    </td>
40</table>
41
42<p><a href="#Introduction">
43      Introduction</a><br>
44&nbsp;&nbsp;&nbsp; <a href="#Acknowledgement">Acknowledgement</a><br>
45&nbsp;&nbsp; &nbsp;<a href="#Preliminary-implementation">Preliminary implementation</a><br>
46<a href="#Requirements">Requirements</a><br>
47<a href="#Issues">Issues</a><br>
48<a href="#Design-decisions">
49      Design decisions</a><br>
50&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-separate-relative">Provide separate lexical and
51      operational <code>relative</code> functions</a><br>
52&nbsp;&nbsp;&nbsp; <a href="#Provide-separate-proximate">Provide
53separate lexical and operational <code>proximate</code> functions</a><br>
54&nbsp;&nbsp;&nbsp; <a href="#Add-lexical-functions">Add lexical functions as <code>path</code> member functions</a><br>
55&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-normal">Provide a non-member function
56<code>lexically_normal</code> returning a
57      normal form path</a><br>
58&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Provide-weakly">Provide a <code>weakly_canonical</code> operational function</a><br>
59&nbsp;&nbsp;&nbsp;&nbsp;<a href="#just-work">Resolve issues in ways that &quot;just work&quot; for users</a><br>
60&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mismatch">Specify <code>lexical relative</code> in terms
61      of <code>std::mismatch</code></a><br>
62&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Specify-op-rel-weakly">Specify operational <code>relative</code> in terms of <code>
63      weakly_canonical</code></a><br>
64&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Specify-op-rel-lex-rel">Specify operational <code>relative</code> in terms of
65      <code>lexically
66      relative</code></a><br>
67<a href="#Proposed-wording">Proposed wording</a><br>
68&nbsp;&nbsp;&nbsp; <a href="#Define-normal-form">Define <i>normal form</i></a><br>
69&nbsp;&nbsp;&nbsp; <a href="#New-class-path-member-functions">New class path member functions</a><br>
70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Synopsis-path">Synopsis</a><br>
71&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Specification-path">Specification</a><br>
72&nbsp;&nbsp;&nbsp; <a href="#operational-functions">New operational functions</a><br>
73&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Synopsis-ops">Synopsis</a><br>
74&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#Specification-ops">Specification</a></p>
75
76<h2>
77      <a name="Introduction">Introduction</a></h2>
78
79<p>There have been requests for a Filesystem library relative function for at
80      least ten years.</p>
81
82<p>
83      The requested functionality seems simple - given two paths with a common
84      prefix, return the non-common suffix portion of one of the paths such that
85      it is relative to the other path.</p>
86
87<p>
88      In terms of the Filesystem library,</p>
89
90<blockquote>
91  <pre>path p(&quot;/a/b/c&quot;);
92path base(&quot;/a/b&quot;);
93path rel = relative(p, base);  // the requested function
94cout &lt;&lt; rel &lt;&lt; endl;           // outputs &quot;c&quot;
95assert(absolute(rel, base) == p);</pre>
96</blockquote>
97<p>If that was all there was to it, the Filesystem library would have had a
98<code>relative</code> function years ago.</p>
99<blockquote>
100<p>Blocking issues: Clashing requirements, symlinks, directory placeholders (<i>dot</i>,
101<i>dot-dot</i>), user-expectations, corner cases.</p>
102</blockquote>
103<h3><a name="Acknowledgement">Acknowledgement</a></h3>
104<p>A paper by Jamie Allsop, <i>Additions to Filesystem supporting Relative Paths</i>,
105is what broke my mental logjam. Much of what follows is based directly on
106Jamie&#39;s analysis and proposal. The <code>weakly_canonical</code> function and
107aspects of the semantic specifications are my contributions. Mistakes, of
108course, are mine.</p>
109<h3><a name="Preliminary-implementation">Preliminary implementation</a></h3>
110<p>A preliminary implementation is available in the
111<a href="https://github.com/boostorg/filesystem/tree/feature/relative2">
112feature/relative2</a> branch of the Boost Filesystem Git repository. See
113<a href="https://github.com/boostorg/filesystem/tree/feature/relative2">
114github.com/boostorg/filesystem/tree/feature/relative2</a></p>
115<h2><a name="Requirements">Requirements</a></h2>
116<b><a name="Requirement-1">Requirement 1</a>:</b> Some uses require symlinks be followed; i.e. the path must be resolved in
117  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
118  resolved in the actual file system.</p>
119<b><a name="Requirement-3">Requirement 3</a>: </b>Some uses require removing redundant current directory (<i>dot</i>)
120  or parent directory (<i>dot-dot</i>) placeholders.<p><b>
121<a name="Requirement-4">Requirement 4</a>: </b>Some uses do not require removing redundant current directory (<i>dot</i>)
122  or parent directory (<i>dot-dot</i>) placeholders since the path is known to
123be
124already in normal form.</p>
125<h2><a name="Issues">Issues</a></h2>
126<p><b><a name="Issue-1">Issue 1</a>:</b> What happens if <code>p</code>
127and <code>base</code> are themselves relative?</p>
128<b><a name="Issue-2">Issue 2</a>:</b> What happens if there is no common prefix? Is this an error, the whole of
129  <code>p</code> is relative to <code>base</code>, or something else?<p><b>
130<a name="Issue-3">Issue 3</a>:</b> What happens if <code>p</code>, <code>base</code>, or both are empty?</p>
131<b><a name="Issue-4">Issue 4</a>:</b> What happens if <code>p</code> and <code>base</code> are the same?<p>
132<b><a name="Issue-5">Issue 5</a>:</b> How is the &quot;common prefix&quot; determined?</p>
133<b><a name="Issue-6">Issue 6</a>:</b> What happens if portions of <code>p</code> or <code>base</code> exist but
134  the entire path does not exist and yet symlinks need to be followed?<p><b>
135<a name="Issue-7">Issue 7</a>:</b> What happens when a symlink in the existing portion of a path is affected
136  by a directory (<i>dot-dot</i>) placeholder in a later non-existent portion of
137  the path?</p>
138<p><b><a name="Issue-8">Issue 8</a>:</b> Overly complex semantics (and thus
139specifications) in preliminary designs made reasoning about uses difficult.</p>
140<p><b><a name="Issue-9">Issue 9</a>: </b>Some uses never have redundant current directory (<i>dot</i>)
141  or parent directory (<i>dot-dot</i>) placeholders, so a removal operation
142  would be an unnecessary expense although otherwise harmless.</p>
143
144<h2>
145      <a name="Design-decisions">Design decisions</a></h2>
146
147<h4>
148      <a name="Provide-separate-relative">Provide separate</a> lexical and
149      operational <code>relative</code> functions</h4>
150
151<p align="left">
152      Resolves the conflict between <a href="#Requirement-1">requirement 1</a>
153      and <a href="#Requirement-2">requirement 2</a> and ensures both
154      requirements are met.</p>
155
156<p>
157      A purely lexical function is needed by users working with directory
158      hierarchies that do not actually exist.</p>
159
160<p>
161      An operational function that queries the current file system for existence
162      and follows symlinks is needed by users working with actual existing
163      directory hierarchies.</p>
164
165<h4>
166      <a name="Provide-separate-proximate">Provide separate</a> lexical and operational
167      <code>proximate</code> functions</h4>
168
169<p>
170      Although not the only possibility, a likely fallback when the relative
171      functions cannot find a relative path is to return the path being made relative. As
172      a convenience, the <code>proximate</code> functions do just that.</p>
173
174<h4>
175      <a name="Add-lexical-functions">Add lexical functions as
176      <code>path</code> member functions</a></h4>
177
178<p dir="ltr">
179      The Filesystem library is unusual in that it has several functions with
180      both lexical (i.e. cheap) and operational (i.e. expensive due to file
181      system access) forms with differing semantics. It is important that users
182      choose the form that meets their application&#39;s specific needs. The library
183      has always made the distinction via the convention of lexical functions
184      being members of class <code>path</code>, while operational functions are
185      non-member functions. The lexical functions proposed here also use the
186      name prefix <code>lexically_</code> to drive home the distinction.</p>
187
188<p>
189      For the contrary argument, see Sutter and Alexandrescu, <i>C++ Coding Standards</i>, 44:
190      &quot;Prefer writing nonmember nonfriend functions&quot;, and Meyers, <i>Effective C++ Third Edition</i>, 23:
191      &quot;Prefer non-member non-friend functions to member functions.&quot;</p>
192
193<h4>
194      <a name="Provide-normal">Provide</a><b> </b>a non-member function <code>
195      <a href="#normal">lexically_normal</a></code> returning a
196      <a href="#normal-form">normal form</a> path</h4>
197
198<p>
199      Enables resolution of <a href="#Requirement-3">requirement 3</a> and
200      <a href="#Requirement-4">requirement 4</a> in a way consistent with
201      <a href="#Issue-9">issue 9</a>. Is a contributor to the resolution of
202      <a href="#Issue-8">issue 8</a>.</p>
203
204<p>
205      &quot;Normalization&quot; is the process of removing redundant current directory (<i>dot</i>)
206      , parent
207      directory (<i>dot-dot</i>), and directory separator elements.</p>
208
209<p>
210      Normalization is a byproduct the current <code>canonical</code> function.
211      But for the path returned by the
212      proposed <code><a href="#weakly_canonical">weakly_canonical</a></code> function,
213      only any leading canonic portion is in canonical form. So any trailing
214      portion of the returned path has not been normalized.</p>
215
216<p>
217      Jamie Allsop has proposed adding a separate normalization function returning a
218      path, and I agree with him.</p>
219
220<p>
221      Boost.filesystem has a deprecated non-const normalization function that
222      modifies the path, but I agree with Jamie that a function returning a path
223      is a better solution.</p>
224
225<h4>
226      <a name="Provide-weakly">Provide</a><b> </b>a <code><a href="#weakly_canonical">weakly_canonical</a></code> operational function</h4>
227
228<p>
229      Resolves <a href="#Issue-6">issue 6</a>, <a href="#Issue-7">issue 7</a>,
230      <a href="#Issue-9">issue 9</a>, and is a contributor to the resolution of
231      <a href="#Issue-8">issue 8</a>.</p>
232
233<p>
234      The operational function
235      <code>weakly_canonical(p)</code> returns a path composed of <code>
236      canonical(x)/y</code>, where <code>x</code> is a path composed of the
237      longest leading sequence of elements in <code>p</code> that exist, and
238      <code>y</code> is a path composed of the remaining trailing non-existent elements of
239      <code>p</code> if any. &quot;<code>weakly</code>&quot; refers to weakened existence
240      requirements compared to the existing canonical function.</p>
241
242<ul>
243  <li>Having <code>weakly_canonical</code> as a separate function, and then
244  specifying the processing of operational <code>relative</code> arguments in
245  terms of calls to <code>weakly_canonical</code> makes it much easier to
246  specify the operational <code>relative</code> function and reason about it.
247  The difficulty of reasoning about operational <code>relative</code>
248  semantics before the invention of <code>weakly_canonical</code> was what led to its
249  initial development.</li>
250  <li>Having <code>weakly_canonical</code> as a separate function also allows
251  use in other contexts.</li>
252  <li>Specifying the return be in <a href="#normal-form">normal form</a> is an
253  engineering trade-off to resolve <a href="#Issue-7">issue 7</a> in a way that
254  just works for most use cases.</li>
255  <li>Specifying normative encouragement to not perform unneeded normalization
256  is a reasonable resolution for <a href="#Issue-9">issue 9</a>.</li>
257</ul>
258
259<h4>
260      Resolve issues in ways that &quot;<a name="just-work">just work</a>&quot; for users</h4>
261
262<p>
263      Resolves issues <a href="#Issue-1">1</a>, <a href="#Issue-2">2</a>,
264      <a href="#Issue-3">3</a>, <a href="#Issue-4">4</a>, <a href="#Issue-7">6</a>,
265      and <a href="#Issue-7">7</a>. Is a contributor to the resolution of
266      <a href="#Issue-8">issue 8</a>.</p>
267
268<p>
269      The &quot;just works&quot; approach was suggested by Jamie Allsop. It is implemented
270      by specifying a reasonable return value for all of the &quot;What happens
271      if...&quot; corner case issues, rather that treating them as hard errors
272      requiring an exception or error code.</p>
273
274<h4>
275      Specify <a href="#lex-proximate"><code>lexically relative</code></a> in terms
276      of <code>std::<a name="mismatch">mismatch</a></code></h4>
277
278<p>
279      Resolves <a href="#Issue-5">issue 5</a>. Is a contributor to the
280      resolution of <a href="#Issue-8">issue 8</a>.</p>
281
282<h4>
283      <a name="Specify-op-rel-weakly">Specify</a> <a href="#op-proximate">operational <code>relative</code></a> in terms of <code>
284      <a href="#weakly_canonical">weakly_canonical</a></code></h4>
285
286<p>
287      Is a contributor to the resolution of <a href="#Issue-8">issue 8</a>.</p>
288
289<ul>
290  <li>Covers a wide range of uses cases since a single function works for
291  existing, non-existing, and partially existing paths.</li>
292  <li>Works correctly for partially existing paths that contain symlinks.</li>
293</ul>
294
295<h4>
296      <a name="Specify-op-rel-lex-rel">Specify</a> <a href="#op-proximate">operational <code>relative</code></a> in terms of
297      <a href="#lex-proximate"><code>lexically
298      relative</code></a></h4>
299
300<p>
301      Is a contributor to the resolution of <a href="#Issue-5">issue 5</a> and
302      <a href="#Issue-8">issue 8</a>.</p>
303
304<p>
305      If would be confusing to users and difficult to specify correctly if the
306      two functions had differing semantics:</p>
307<ul>
308  <li>When either or both paths are empty.</li>
309  <li>When all elements of the two paths match exactly.</li>
310  <li>Because different matching algorithms were used.</li>
311  <li>Because although the same matching algorithm was used, it was applied in different ways.</li>
312</ul>
313
314<p>
315      These problems are avoided by specifying operational <code>relative</code>
316      in terms of lexical <code>relative</code> after preparatory
317      calls to operational functions.</p>
318
319<h2><a name="Proposed-wording">Proposed wording</a></h2>
320
321<p><span style="background-color: #DBDBDB"><i>&quot;Overview:&quot; sections below are
322non-normative experiments attempting to make the normative reference
323specifications easier to grasp.</i></span></p>
324
325<h3><a name="Define-normal-form">Define <i>normal form</i></a></h3>
326
327<p>A path is in <b><i><a name="normal-form">normal form</a></i></b> if it has no
328redundant current directory (<i>dot</i>) or parent directory (<i>dot-dot</i>)
329elements. The normal form for an empty path is an empty path. The normal form
330for a path ending in a <i>directory-separator</i> that is not the root directory
331is the same path with a current directory (<i>dot</i>) element appended.</p>
332
333<p><span style="background-color: #DBDBDB"><i>The last sentence above is not
334necessary for POSIX-like or Windows-like operating systems, but supports systems
335like OpenVMS that use different syntax for directory and regular-file names.</i></span></p>
336
337<h3><a name="New-class-path-member-functions">New class path member functions</a></h3>
338
339<h4><a name="Synopsis-path">Synopsis</a></h4>
340
341<pre>path lexically_normal() const;
342path lexically_relative(const path&amp; base) const;
343path lexically_proximate(const path&amp; base) const;</pre>
344
345<h4><a name="Specification-path">Specification</a></h4>
346
347
348<pre>path <a name="lex-normal">lexically_normal</a>() const;</pre>
349<blockquote>
350<p><i>Overview:</i> Returns <code>*this</code> with redundant current directory
351(<i>dot</i>), parent directory (<i>dot-dot</i>), and <i>directory-separator</i> elements removed.</p>
352<p><i>Returns:</i> <code>*this</code> in <a href="#normal-form">normal form</a>.</p>
353<p><i>Remarks:</i> Uses <code>operator/=</code> to compose the returned path.</p>
354<p>[<i>Example:</i></p>
355<p><code>assert(path(&quot;foo/./bar/..&quot;).lexically_normal() == &quot;foo&quot;);<br>
356assert(path(&quot;foo/.///bar/../&quot;).lexically_normal() == &quot;foo/.&quot;);</code></p>
357<p>The above assertions will succeed.<i> </i>On Windows, the
358returned path&#39;s <i>directory-separator</i> characters will be backslashes rather than slashes, but that
359does not affect <code>path</code> equality.<i> —end example</i>]</p>
360</blockquote>
361
362<pre>path <a name="lex-relative">lexically_relative</a>(const path&amp; base) const;</pre>
363  <blockquote>
364  <p><i>Overview:</i> Returns <code>*this</code> made relative to <code>base</code>.
365  Treats empty or identical paths as corner cases, not errors. Does not resolve
366  symlinks. Does not first normalize <code>*this</code> or <code>base</code>.</p>
367
368  <p><i>Remarks:</i> Uses <code>std::mismatch(begin(), end(), base.begin(), base.end())</code>, to determine the first mismatched element of
369  <code>*this</code> and <code>base</code>. Uses <code>operator==</code> to
370  determine if elements match. </p>
371
372  <p><i>Returns:</i> </p>
373
374  <ul>
375    <li>
376  <code>path()</code> if the first mismatched element of <code>*this</code> is equal to <code>
377  begin()</code> or the first mismatched element
378  of <code>base</code> is equal to <code>base.begin()</code>, or<br>&nbsp;
379    </li>
380    <li>
381  <code>path(&quot;.&quot;)</code> if the first mismatched element of <code>
382  *this</code> is equal to <code>
383  end()</code> and the first mismatched element
384  of <code>base</code> is equal to <code>base.end()</code>, or<br>&nbsp;
385    </li>
386    <li>An object of class <code>path</code> composed via application of <code>
387    operator/= path(&quot;..&quot;)</code> for each element in the half-open
388    range [first
389    mismatched element of <code>base</code>, <code>base.end()</code>), and then
390    application of <code>operator/=</code> for each element in the half-open
391    range
392    [first mismatched element of <code>*this</code>, <code>end()</code>).
393    </li>
394</ul>
395
396<p>[<i>Example:</i></p>
397<p><code>assert(path(&quot;/a/d&quot;).lexically_relative(&quot;/a/b/c&quot;) ==  &quot;../../d&quot;);<br>
398assert(path(&quot;/a/b/c&quot;).lexically_relative(&quot;/a/d&quot;) ==  &quot;../b/c&quot;);<br>
399assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a&quot;) == &quot;b/c&quot;);<br>
400assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a/b/c/x/y&quot;) ==  &quot;../..&quot;);<br>
401assert(path(&quot;a/b/c&quot;).lexically_relative(&quot;a/b/c&quot;) ==  &quot;.&quot;);<br>
402assert(path(&quot;a/b&quot;).lexically_relative(&quot;c/d&quot;) ==  &quot;&quot;);</code></p>
403<p>The above assertions will succeed.<i> </i>On Windows, the
404returned path&#39;s <i>directory-separator</i>s will be backslashes rather than
405forward slashes, but that
406does not affect <code>path</code> equality.<i> —end example</i>]</p>
407
408  <p>[<i>Note:</i> If symlink following semantics are desired, use the  operational function <code>
409  <a href="#op-proximate">relative</a></code>&nbsp; <i>—end note</i>]</p>
410
411  <p>[<i>Note:</i> If <a href="#normal">normalization</a> is needed to ensure
412  consistent matching of elements, apply <code><a href="#normal">lexically_normal()</a></code>
413  to <code>*this</code>, <code>base</code>, or both. <i>—end note</i>]</p>
414
415</blockquote>
416
417
418<pre>path <a name="lex-proximate">lexically_proximate</a>(const path&amp; base) const;</pre>
419
420  <blockquote>
421
422  <p><i>Returns:</i> If the value of <code>lexically_relative(base)</code> is
423  not an empty path, return it. Otherwise return <code>*this</code>.</p>
424
425  <p>[<i>Note:</i> If symlink following semantics are desired, use the  operational function
426  <code><a href="#op-proximate">proximate</a></code>&nbsp; <i>—end note</i>]</p>
427
428  <p>[<i>Note:</i> If <a href="#normal">normalization</a> is needed to ensure
429  consistent matching of elements, apply <code><a href="#normal">lexically_normal()</a></code>
430  to <code>*this</code>, <code>base</code>, or both. <i>—end note</i>]</p>
431
432</blockquote>
433
434
435<h3>New <a name="operational-functions">operational functions</a></h3>
436
437
438<h4><a name="Synopsis-ops">Synopsis</a></h4>
439
440
441<pre>path weakly_canonical(const path&amp; p);
442path weakly_canonical(const path&amp; p, system::error_code&amp; ec);
443path relative(const path&amp; p, system::error_code&amp; ec);
444path relative(const path&amp; p, const path&amp; base=current_path());
445path relative(const path&amp; p, const path&amp; base, system::error_code&amp; ec);
446path proximate(const path&amp; p, system::error_code&amp; ec);
447path proximate(const path&amp; p, const path&amp; base=current_path());
448path proximate(const path&amp; p, const path&amp; base, system::error_code&amp; ec);
449</pre>
450<h4><a name="Specification-ops">Specification</a></h4>
451
452<pre>path <a name="weakly_canonical">weakly_canonical</a>(const path&amp; p);
453path weakly_canonical(const path&amp; p, system::error_code&amp; ec);</pre>
454<blockquote>
455<i>Overview:</i> Returns <code>p</code> with symlinks resolved and the result
456normalized.<p>
457<i>Returns: </i>
458A path composed of the result of calling the <code>canonical</code> function on
459a path composed of the leading elements of <code>p</code> that exist, if any,
460followed by the elements of <code>p</code> that do not exist, if any.</p>
461<p><i>Postcondition:</i> The returned path is in <a href="#normal">normal form</a>.</p>
462<p><i>Remarks:</i> Uses <code>operator/=</code> to compose the returned path.
463Uses the <code>status</code> function to determine existence.</p>
464<p><i>Remarks:</i> Implementations are encouraged to avoid unnecessary
465normalization such as when <code>canonical</code> has already been called on the
466entirety of <code>p</code>.</p>
467<p><i>Throws:</i>&nbsp; As specified in Error reporting.</p>
468</blockquote>
469<pre>path <a name="op-relative">relative</a>(const path&amp; p, system::error_code&amp; ec);</pre>
470<blockquote>
471<p><i>Returns:</i> <code>relative(p, current_path(), ec)</code>.</p>
472  <p><i>Throws:</i>&nbsp; As specified in Error reporting.</p>
473
474  </blockquote>
475<pre>path relative(const path&amp; p, const path&amp; base=current_path());
476path relative(const path&amp; p, const path&amp; base, system::error_code&amp; ec);</pre>
477<blockquote>
478  <p><i>Overview:</i> Returns <code>p</code> made relative to <code>
479  base</code>. Treats empty or identical paths as corner cases, not errors.
480  Resolves symlinks and normalizes both <code>p</code> and <code>base</code>
481  before other processing.</p>
482
483<p><i>Returns:</i> <code><a href="#weakly_canonical">weakly_canonical</a>(p).l<a href="#lex-proximate">exically_relative</a>(<a href="#weakly_canonical">weakly_canonical</a>(base))</code>. The second form returns <code>path()</code> if an error occurs.</p>
484  <p><i>Throws:</i> As specified in Error reporting.</p>
485</blockquote>
486
487<pre>path <a name="op-proximate">proximate</a>(const path&amp; p, system::error_code&amp; ec);</pre>
488<blockquote>
489<p><i>Returns:</i> <code>proximate(p, current_path(), ec)</code>.</p>
490  <p><i>Throws:</i>&nbsp; As specified in Error reporting.</p>
491
492  </blockquote>
493<pre>path proximate(const path&amp; p, const path&amp; base=current_path());
494path proximate(const path&amp; p, const path&amp; base, system::error_code&amp; ec);</pre>
495<blockquote>
496
497<p><i>Returns:</i> <code><a href="#weakly_canonical">weakly_canonical</a>(p).l<a href="#lex-proximate">exically_proximate</a>(<a href="#weakly_canonical">weakly_canonical</a>(base))</code>. The second form returns <code>path()</code> if an error occurs.</p>
498  <p><i>Throws:</i> As specified in Error reporting.</p>
499</blockquote>
500
501<hr>
502<p>&copy; Copyright Beman Dawes 2015</p>
503<p>Distributed under the Boost Software License, Version 1.0. See
504<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
505<p>Revised
506<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->25 October 2015<!--webbot bot="Timestamp" endspan i-checksum="32445" --></p>
507
508</body>
509
510</html>
511