I am using a new and modern C++17 with the filesystem API. I am working in Windows, with Visual Studio 2017.
The following code gives an unexpected result:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path path(R"(D:\dir\file.cpp)");
for (auto& dir : path)
{
std::cout<<dir<<std::endl;
}
}
Result is:
"D:"
"\\"
"dir"
"file.cpp"
Why was "\\" printed?
Testing this in GCC 9.1.0 (please change '\' to '/' in the path variable), the result is:
"D:"
"dir"
"file.cpp"
Why is the behavior different?
Which result is correct according to the C++17 standard?
See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#fully-qualified-vs-relative-paths for some information on windows path names.
The C++ standard has this to say about path iterators ([fs.path.itr]/4):
For the elements of the pathname in the generic format, the forward traversal order is as follows:
- The root-name element, if present.
- The root-directory element, if present. [ Note: The generic format is required to ensure lexicographical comparison works correctly. — end note]
- Each successive filename element, if present.
- An empty element, if a trailing non-root directory-separator is present.
On windows, the path D:\dir\file.cpp
has a disk designator of D:
, followed by the root directory on that disk, \
, then the path of dir
, file.cpp
. According to windows, D:
is a root-name, so \
is a root-directory. You could have D:dir\file.cpp
, but note that this is now a relative path.
On gcc, if not on windows, D:
will be treated as a regular directory name (The same as ./D:/dir/file.cpp
). So, there is no root-name or root-directory. If you had instead had /D:/dir/file.cpp
, the iterator would have contained /
, D:
, dir
, file.cpp
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With