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">
14 <table border=
"0" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse" bordercolor=
"#111111">
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>
20 <font size=
"7">Filesystem Relative
<br>
26 <table border=
"0" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse"
27 bordercolor=
"#111111" bgcolor=
"#D7EEFF" width=
"100%">
29 <td><a href=
"index.htm">Home
</a>
30 <a href=
"tutorial.html">Tutorial
</a>
31 <a href=
"reference.html">Reference
</a>
32 <a href=
"faq.htm">FAQ
</a>
33 <a href=
"release_history.html">Releases
</a>
34 <a href=
"portability_guide.htm">Portability
</a>
35 <a href=
"v3.html">V3 Intro
</a>
36 <a href=
"v3_design.html">V3 Design
</a>
37 <a href=
"deprecated.html">Deprecated
</a>
38 <a href=
"issue_reporting.html">Bug Reports
</a>
42 <p><a href=
"#Introduction">
44 <a href=
"#Acknowledgement">Acknowledgement
</a><br>
45 <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 <a href=
"#Provide-separate-relative">Provide separate lexical and
51 operational
<code>relative
</code> functions
</a><br>
52 <a href=
"#Provide-separate-proximate">Provide
53 separate lexical and operational
<code>proximate
</code> functions
</a><br>
54 <a href=
"#Add-lexical-functions">Add lexical functions as
<code>path
</code> member functions
</a><br>
55 <a href=
"#Provide-normal">Provide a non-member function
56 <code>lexically_normal
</code> returning a
57 normal form path
</a><br>
58 <a href=
"#Provide-weakly">Provide a
<code>weakly_canonical
</code> operational function
</a><br>
59 <a href=
"#just-work">Resolve issues in ways that
"just work
" for users
</a><br>
60 <a href=
"#mismatch">Specify
<code>lexical relative
</code> in terms
61 of
<code>std::mismatch
</code></a><br>
62 <a href=
"#Specify-op-rel-weakly">Specify operational
<code>relative
</code> in terms of
<code>
63 weakly_canonical
</code></a><br>
64 <a href=
"#Specify-op-rel-lex-rel">Specify operational
<code>relative
</code> in terms of
66 relative
</code></a><br>
67 <a href=
"#Proposed-wording">Proposed wording
</a><br>
68 <a href=
"#Define-normal-form">Define
<i>normal form
</i></a><br>
69 <a href=
"#New-class-path-member-functions">New class path member functions
</a><br>
70 <a href=
"#Synopsis-path">Synopsis
</a><br>
71 <a href=
"#Specification-path">Specification
</a><br>
72 <a href=
"#operational-functions">New operational functions
</a><br>
73 <a href=
"#Synopsis-ops">Synopsis
</a><br>
74 <a href=
"#Specification-ops">Specification
</a></p>
77 <a name=
"Introduction">Introduction
</a></h2>
79 <p>There have been requests for a Filesystem library relative function for at
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>
88 In terms of the Filesystem library,
</p>
91 <pre>path p(
"/a/b/c
");
92 path base(
"/a/b
");
93 path rel = relative(p, base); // the requested function
94 cout
<< rel
<< endl; // outputs
"c
"
95 assert(absolute(rel, base) == p);
</pre>
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>
100 <p>Blocking issues: Clashing requirements, symlinks, directory placeholders (
<i>dot
</i>,
101 <i>dot-dot
</i>), user-expectations, corner cases.
</p>
103 <h3><a name=
"Acknowledgement">Acknowledgement
</a></h3>
104 <p>A paper by Jamie Allsop,
<i>Additions to Filesystem supporting Relative Paths
</i>,
105 is what broke my mental logjam. Much of what follows is based directly on
106 Jamie
's analysis and proposal. The
<code>weakly_canonical
</code> function and
107 aspects of the semantic specifications are my contributions. Mistakes, of
108 course, 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">
112 feature/relative2
</a> branch of the Boost Filesystem Git repository. See
113 <a href=
"https://github.com/boostorg/filesystem/tree/feature/relative2">
114 github.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
124 already 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>
127 and
<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
"common prefix
" 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
138 <p><b><a name=
"Issue-8">Issue
8</a>:
</b> Overly complex semantics (and thus
139 specifications) 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>
145 <a name=
"Design-decisions">Design decisions
</a></h2>
148 <a name=
"Provide-separate-relative">Provide separate
</a> lexical and
149 operational
<code>relative
</code> functions
</h4>
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>
157 A purely lexical function is needed by users working with directory
158 hierarchies that do not actually exist.
</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>
166 <a name=
"Provide-separate-proximate">Provide separate
</a> lexical and operational
167 <code>proximate
</code> functions
</h4>
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>
175 <a name=
"Add-lexical-functions">Add lexical functions as
176 <code>path
</code> member functions
</a></h4>
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
'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>
189 For the contrary argument, see Sutter and Alexandrescu,
<i>C++ Coding Standards
</i>,
44:
190 "Prefer writing nonmember nonfriend functions
", and Meyers,
<i>Effective C++ Third Edition
</i>,
23:
191 "Prefer non-member non-friend functions to member functions.
"</p>
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>
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>
205 "Normalization
" is the process of removing redundant current directory (
<i>dot
</i>)
207 directory (
<i>dot-dot
</i>), and directory separator elements.
</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>
217 Jamie Allsop has proposed adding a separate normalization function returning a
218 path, and I agree with him.
</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>
226 <a name=
"Provide-weakly">Provide
</a><b> </b>a
<code><a href=
"#weakly_canonical">weakly_canonical
</a></code> operational function
</h4>
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>
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.
"<code>weakly
</code>" refers to weakened existence
240 requirements compared to the existing canonical function.
</p>
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>
260 Resolve issues in ways that
"<a name=
"just-work">just work
</a>" for users
</h4>
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>
269 The
"just works
" approach was suggested by Jamie Allsop. It is implemented
270 by specifying a reasonable return value for all of the
"What happens
271 if...
" corner case issues, rather that treating them as hard errors
272 requiring an exception or error code.
</p>
275 Specify
<a href=
"#lex-proximate"><code>lexically relative
</code></a> in terms
276 of
<code>std::
<a name=
"mismatch">mismatch
</a></code></h4>
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>
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>
287 Is a contributor to the resolution of
<a href=
"#Issue-8">issue
8</a>.
</p>
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>
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>
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>
305 If would be confusing to users and difficult to specify correctly if the
306 two functions had differing semantics:
</p>
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>
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>
319 <h2><a name=
"Proposed-wording">Proposed wording
</a></h2>
321 <p><span style=
"background-color: #DBDBDB"><i>"Overview:
" sections below are
322 non-normative experiments attempting to make the normative reference
323 specifications easier to grasp.
</i></span></p>
325 <h3><a name=
"Define-normal-form">Define
<i>normal form
</i></a></h3>
327 <p>A path is in
<b><i><a name=
"normal-form">normal form
</a></i></b> if it has no
328 redundant current directory (
<i>dot
</i>) or parent directory (
<i>dot-dot
</i>)
329 elements. The normal form for an empty path is an empty path. The normal form
330 for a path ending in a
<i>directory-separator
</i> that is not the root directory
331 is the same path with a current directory (
<i>dot
</i>) element appended.
</p>
333 <p><span style=
"background-color: #DBDBDB"><i>The last sentence above is not
334 necessary for POSIX-like or Windows-like operating systems, but supports systems
335 like OpenVMS that use different syntax for directory and regular-file names.
</i></span></p>
337 <h3><a name=
"New-class-path-member-functions">New class path member functions
</a></h3>
339 <h4><a name=
"Synopsis-path">Synopsis
</a></h4>
341 <pre>path lexically_normal() const;
342 path lexically_relative(const path
& base) const;
343 path lexically_proximate(const path
& base) const;
</pre>
345 <h4><a name=
"Specification-path">Specification
</a></h4>
348 <pre>path
<a name=
"lex-normal">lexically_normal
</a>() const;
</pre>
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(
"foo/./bar/..
").lexically_normal() ==
"foo
");
<br>
356 assert(path(
"foo/.///bar/../
").lexically_normal() ==
"foo/.
");
</code></p>
357 <p>The above assertions will succeed.
<i> </i>On Windows, the
358 returned path
's
<i>directory-separator
</i> characters will be backslashes rather than slashes, but that
359 does not affect
<code>path
</code> equality.
<i> —end example
</i>]
</p>
362 <pre>path
<a name=
"lex-relative">lexically_relative
</a>(const path
& base) const;
</pre>
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>
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>
372 <p><i>Returns:
</i> </p>
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>
381 <code>path(
".
")
</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>
386 <li>An object of class
<code>path
</code> composed via application of
<code>
387 operator/= path(
"..
")
</code> for each element in the half-open
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
392 [first mismatched element of
<code>*this
</code>,
<code>end()
</code>).
396 <p>[
<i>Example:
</i></p>
397 <p><code>assert(path(
"/a/d
").lexically_relative(
"/a/b/c
") ==
"../../d
");
<br>
398 assert(path(
"/a/b/c
").lexically_relative(
"/a/d
") ==
"../b/c
");
<br>
399 assert(path(
"a/b/c
").lexically_relative(
"a
") ==
"b/c
");
<br>
400 assert(path(
"a/b/c
").lexically_relative(
"a/b/c/x/y
") ==
"../..
");
<br>
401 assert(path(
"a/b/c
").lexically_relative(
"a/b/c
") ==
".
");
<br>
402 assert(path(
"a/b
").lexically_relative(
"c/d
") ==
"");
</code></p>
403 <p>The above assertions will succeed.
<i> </i>On Windows, the
404 returned path
's
<i>directory-separator
</i>s will be backslashes rather than
405 forward slashes, but that
406 does not affect
<code>path
</code> equality.
<i> —end example
</i>]
</p>
408 <p>[
<i>Note:
</i> If symlink following semantics are desired, use the operational function
<code>
409 <a href=
"#op-proximate">relative
</a></code> <i>—end note
</i>]
</p>
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>
418 <pre>path
<a name=
"lex-proximate">lexically_proximate
</a>(const path
& base) const;
</pre>
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>
425 <p>[
<i>Note:
</i> If symlink following semantics are desired, use the operational function
426 <code><a href=
"#op-proximate">proximate
</a></code> <i>—end note
</i>]
</p>
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>
435 <h3>New
<a name=
"operational-functions">operational functions
</a></h3>
438 <h4><a name=
"Synopsis-ops">Synopsis
</a></h4>
441 <pre>path weakly_canonical(const path
& p);
442 path weakly_canonical(const path
& p, system::error_code
& ec);
443 path relative(const path
& p, system::error_code
& ec);
444 path relative(const path
& p, const path
& base=current_path());
445 path relative(const path
& p, const path
& base, system::error_code
& ec);
446 path proximate(const path
& p, system::error_code
& ec);
447 path proximate(const path
& p, const path
& base=current_path());
448 path proximate(const path
& p, const path
& base, system::error_code
& ec);
450 <h4><a name=
"Specification-ops">Specification
</a></h4>
452 <pre>path
<a name=
"weakly_canonical">weakly_canonical
</a>(const path
& p);
453 path weakly_canonical(const path
& p, system::error_code
& ec);
</pre>
455 <i>Overview:
</i> Returns
<code>p
</code> with symlinks resolved and the result
458 A path composed of the result of calling the
<code>canonical
</code> function on
459 a path composed of the leading elements of
<code>p
</code> that exist, if any,
460 followed 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.
463 Uses the
<code>status
</code> function to determine existence.
</p>
464 <p><i>Remarks:
</i> Implementations are encouraged to avoid unnecessary
465 normalization such as when
<code>canonical
</code> has already been called on the
466 entirety of
<code>p
</code>.
</p>
467 <p><i>Throws:
</i> As specified in Error reporting.
</p>
469 <pre>path
<a name=
"op-relative">relative
</a>(const path
& p, system::error_code
& ec);
</pre>
471 <p><i>Returns:
</i> <code>relative(p, current_path(), ec)
</code>.
</p>
472 <p><i>Throws:
</i> As specified in Error reporting.
</p>
475 <pre>path relative(const path
& p, const path
& base=current_path());
476 path relative(const path
& p, const path
& base, system::error_code
& ec);
</pre>
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>
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>
487 <pre>path
<a name=
"op-proximate">proximate
</a>(const path
& p, system::error_code
& ec);
</pre>
489 <p><i>Returns:
</i> <code>proximate(p, current_path(), ec)
</code>.
</p>
490 <p><i>Throws:
</i> As specified in Error reporting.
</p>
493 <pre>path proximate(const path
& p, const path
& base=current_path());
494 path proximate(const path
& p, const path
& base, system::error_code
& ec);
</pre>
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>
502 <p>© 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>
506 <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->25 October
2015<!--webbot bot="Timestamp" endspan i-checksum="32445" --></p>