问题
Given below code:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
fs::path fsBase = "/base";
fs::path fsAppend = "/append";
auto fsResult = fsBase / fsAppend;
std::cout << "fsResult: " << fsResult << std::endl;
return 0;
}
Usually, the expected result is /base/append
, but it actually gives /append
.
The description of fs::path::append does indicate this behavior:
If p.is_absolute() || (p.has_root_name() && p.root_name() != root_name()), then replaces the current path with p as if by operator=(p) and finishes.
However, the behavior of std::experimental::filesystem
and boost::filesystem
is different, that gives expected /base/append
.
See examples.
The question is why it behaves like this? Why does it replace the path with append()
function?
回答1:
fsAppend
is an absolute path since it starts with /
and you're on a system such as POSIX where paths starting with /
are absolute.
Appending one absolute path to another absolute path doesn't make any sense (to me throwing an exception would be the most natural result actually). What should the result of C:\foo.txt
append C:\bar.txt
be?
In experimental::fs
the rule was that if the second argument's .native()
started with a directory separator then it was treated as a relative path for append purposes, even though it may be an absolute path in other contexts!
The standardized filesystem clearly distinguishes absolute paths from relative paths, trying to avoid this ambiguity that arises on POSIX systems.
The write-up of the change can be found in P0492R2 US77.
Note that you can use +=
rather than /
for concatenation (should do what you expect), or make the second argument relative before using /
.
Also see this answer for further comparison between experimental
and finalized.
来源:https://stackoverflow.com/questions/55214156/why-does-stdfilesystempathappend-replace-the-current-path-if-p-starts-with