Boost logo

Boost :

Subject: Re: [boost] [filesystem] Request for comments on proposed relative() function
From: Rob Stewart (robertstewart_at_[hidden])
Date: 2014-05-14 05:12:44


On May 13, 2014 10:00:25 PM EDT, Gavin Lambert <gavinl_at_[hidden]> wrote:
>On 9/05/2014 05:19, quoth Beman Dawes:
>> *Returns: *An object of class path containing the first element of p
>that
>> does not have a corresponding element in base, followed by the
>subsequent
>> elements of p appended as if by path::operator/=.
>
>Any chance of including in the docs some example inputs and outputs, or
>
>test cases? I'm having trouble synchronising what I think this method
>ought to be doing with what my understanding of this description
>suggests. (Actually I have similar issues with most of the
>Boost.Filesystem documentation -- possibly I just don't properly grok
>standardese.)

This is a common complaint. Beman always looked toward standardization, so he wrote his docs with that in mind. The problem is that not everyone groks that format.

>Possibly I'm just interpreting it incorrectly, or I'm making an
>incorrect assumption about the internals of path, but this description
>does not sound correct.
>
>> if (mm.first == p.end() || mm.second != base.end())
>> {
>> throw filesystem_error(
>> "p does not begin with base, so can not be made relative to
>base",
>> p, base,
>> error_code(errc::invalid_argument, generic_category()));
>> }
>
>In the event that the provided path cannot be made relative to base,
>isn't it more generically useful to return the original unmodified
>absolute path? (ie. simply returning p instead of throwing, at least
>when both paths are absolute.)

This gets you into the discussion of error codes versus exceptions as a means to report errors.

>I'm assuming that the intended use case of this is to "minimise" a path
>given a known working directory, and unrelated absolute paths are
>already in their minimal form in that context.

That's a reasonable use case, but this function is only about returning the portion of p that is relative to base.

>Or another possibly useful output (as Daniel hinted at, though I don't
>think he got the case right) would be to return a relative path using
>dotdot syntax, so:
>
>BOOST_TEST(fs::relative("/abc", "/abc/def") == path(".."));
>BOOST_TEST(fs::relative("/ghi", "/abc/def") == path("../../ghi"));
>
>This could be more useful in some cases (it bloats the path but makes
>it
>more immune to being moved elsewhere). Maybe we even need both.

Interesting

>Although that brings up another question (which I'm not really familiar
>enough with the "path" class internals to answer by looking at the
>example implementation): is "base" intended to be assumed as a
>directory
>name (which is how most filesystem "make relative" functions typically
>work) or as a file name (which is how URL "make relative" works)?

path makes no assumptions about what it references, or whether the pathname even exists in the filesystem.

>On a peripherally related note, I find the following behaviour (on
>Windows) surprising:
>
>fs::path("C:\\foo") / fs::path("C:\\bar") ==
>fs::path("C:\\foo\\C:\\bar")
>
>Shouldn't appending a root-path discard the prior path, like how
>fs::absolute() works? (I assume this was intentional to simplify the
>implementation, but I was hoping there would be something analogous to
>Path.Combine from .NET, which can also return relative paths.)

Windows makes a mess of these things, but I agree that would be nice.

___
Rob

(Sent from my portable computation engine)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk