On May 13, 2014 10:00:25 PM EDT, Gavin Lambert
*Returns: *An object of class path containing the first element of p
On 9/05/2014 05:19, quoth Beman Dawes: 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)