Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>As of version <a href="http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/reference.html" rel="nofollow noreferrer">1.60.0</a> boost.filesystem does support this. You're looking for the member function <code>path lexically_relative(const path&amp; p) const</code>.</p> <p>Original, pre-1.60.0 answer below.</p> <hr> <p>Boost doesn't support this; it's an open issue &mdash; <a href="https://svn.boost.org/trac/boost/ticket/1976" rel="nofollow noreferrer">#1976 (Inverse function for complete)</a> &mdash; that nevertheless doesn't seem to be getting much traction.</p> <p>Here's a vaguely naive workaround that seems to do the trick (not sure whether it can be improved):</p> <pre><code>#include &lt;boost/filesystem/path.hpp&gt; #include &lt;boost/filesystem/operations.hpp&gt; #include &lt;boost/filesystem/fstream.hpp&gt; #include &lt;stdexcept&gt; /** * https://svn.boost.org/trac/boost/ticket/1976#comment:2 * * "The idea: uncomplete(/foo/new, /foo/bar) =&gt; ../new * The use case for this is any time you get a full path (from an open dialog, perhaps) * and want to store a relative path so that the group of files can be moved to a different * directory without breaking the paths. An IDE would be a simple example, so that the * project file could be safely checked out of subversion." * * ALGORITHM: * iterate path and base * compare all elements so far of path and base * whilst they are the same, no write to output * when they change, or one runs out: * write to output, ../ times the number of remaining elements in base * write to output, the remaining elements in path */ boost::filesystem::path naive_uncomplete(boost::filesystem::path const p, boost::filesystem::path const base) { using boost::filesystem::path; using boost::filesystem::dot; using boost::filesystem::slash; if (p == base) return "./"; /*!! this breaks stuff if path is a filename rather than a directory, which it most likely is... but then base shouldn't be a filename so... */ boost::filesystem::path from_path, from_base, output; boost::filesystem::path::iterator path_it = p.begin(), path_end = p.end(); boost::filesystem::path::iterator base_it = base.begin(), base_end = base.end(); // check for emptiness if ((path_it == path_end) || (base_it == base_end)) throw std::runtime_error("path or base was empty; couldn't generate relative path"); #ifdef WIN32 // drive letters are different; don't generate a relative path if (*path_it != *base_it) return p; // now advance past drive letters; relative paths should only go up // to the root of the drive and not past it ++path_it, ++base_it; #endif // Cache system-dependent dot, double-dot and slash strings const std::string _dot = std::string(1, dot&lt;path&gt;::value); const std::string _dots = std::string(2, dot&lt;path&gt;::value); const std::string _sep = std::string(1, slash&lt;path&gt;::value); // iterate over path and base while (true) { // compare all elements so far of path and base to find greatest common root; // when elements of path and base differ, or run out: if ((path_it == path_end) || (base_it == base_end) || (*path_it != *base_it)) { // write to output, ../ times the number of remaining elements in base; // this is how far we've had to come down the tree from base to get to the common root for (; base_it != base_end; ++base_it) { if (*base_it == _dot) continue; else if (*base_it == _sep) continue; output /= "../"; } // write to output, the remaining elements in path; // this is the path relative from the common root boost::filesystem::path::iterator path_it_start = path_it; for (; path_it != path_end; ++path_it) { if (path_it != path_it_start) output /= "/"; if (*path_it == _dot) continue; if (*path_it == _sep) continue; output /= *path_it; } break; } // add directory level to both paths and continue iteration from_path /= path(*path_it); from_base /= path(*base_it); ++path_it, ++base_it; } return output; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload