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.) 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.) 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. 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. 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)? My examples above assume the former, which seems consistent provided that current_path() never returns a path with trailing directory separator (unless the current path is the root). 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.)