6

I am trying to port from boost::filesystem to std::filesystem. During the process I encountered some code in which boost and std seems to behave in a different way.

The following code shows the behaviour:

#include <iostream> #include <filesystem> #include <boost/filesystem.hpp> template<typename T> void TestOperatorSlash() { const std::string foo = "Foo"; const std::string bar = "Bar"; const T start = "\\"; std::string sep; sep += T::preferred_separator; const auto output = start / (foo + bar) / sep; std::cout << output << '\n'; } int main(int argc, char** argv) { TestOperatorSlash<std::filesystem::path>(); TestOperatorSlash<boost::filesystem::path>(); } 

The code gives in output:

"\\" "\FooBar\" 

The expected behaviour for me is the one of boost, and I don't understand what happens with std::filesystem.

Why do I get "\\"? Why is the behaviour of operator/ of path different in boost and std?

Edit:

After understanding the motivation of the behaviour of std::filesystem::operator/ and given the answer to this question, I decided to use the function path::relative_path() for the second argument of operator/ when I have an absolute path.

In this way I can mimic the behaviour of boost::filesystem. So, for example:

#include <iostream> #include <filesystem> namespace fs = std::filesystem; int main(int argc, char** argv) { fs::path foo = "\\foo"; fs::path bar = "\\bar"; auto foobar0 = foo / bar; // Evaluates to \\bar auto foobar1 = foo / bar.relative_path(); // Evaluates to \\foo\\bar } 
1
  • If you want to generate a final / in a path, you can use / "", which produces a result that is of course one character shorter than using / "a". Commented Sep 4, 2023 at 20:26

1 Answer 1

4

Boost will merge redundant separators.

https://www.boost.org/doc/libs/1_68_0/libs/filesystem/doc/reference.html#path-appends

Appends path::preferred_separator to pathname, converting format and encoding if required ([path.arg.convert]), unless:

an added separator would be redundant, ... 

Whereas std::filesystem sees a leading separator in the second argument of / as an instruction to replace parts or all of the original path:

https://en.cppreference.com/w/cpp/filesystem/path/append

path("C:foo") / "/bar"; // yields "C:/bar" (removes relative path, then appends) 

Did you want:

const auto output = start / (foo + bar) / ""; 

instead?

Sign up to request clarification or add additional context in comments.

1 Comment

I was not aware of the 'replace' mechanism of std::filesystem::path::append. I found here some explaination about it. Thank you for your answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.