Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create_directory() vs. create_directories()

Currently I am trying to work with the std::filesystem. I'm working on Windows 7 64-bit using MinGW-W64 GCC 7.1.0. Since this compiler does not support the std::filesystem, I have to include the experimental version and link with -lstdc++fs.

#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;

This worked fine up to the point where I wanted to create nested directories. If I create the directories one at a time using create_directory(), everything works perfect. Now if I use create_directories() instead, it throws a filesystem_error if one of the directories already exists.

fs::path levelA{"."};
fs::path levelB{"folder"};
fs::path levelAB = levelA / levelB;  // "./folder"

bool create_separately; // set this bool as needed

if (create_separately) {
  /* This works perfectly */
  fs::create_directory(levelA);
  fs::create_directory(levelAB);
}
else {
  /* This throws because "." already exists */
  fs::create_directories(levelAB);
}

Comparing the documentation of the experimental version to the standard version, an additional sentence was added for the standard version:

Executes (1) for every element of p that does not already exist. If p already exists, the function does nothing (this condition is not treated as an error).

Why was this treated as an error in the first place? Is this considered a bug?

Additionaly, is there an easy way to update GCC on Windows? I read something about GCC 8.1.0 being released and some new MinGW version supporting it, but I can't seem to find any downloads.

like image 238
KorbenDose Avatar asked Nov 08 '22 07:11

KorbenDose


1 Answers

Maybe you meant this, but note that only the second sentence you quoted is changed relative to the TS version—and has changed again since this question was asked. It refers to the case where p already exists and might not be a directory; the function returns false to indicate that it did nothing, but at the time of asking it didn’t report any error, regardless of the nature of p. The logic was that most operating systems do not distinguish this situation, so it was left to the application developer to ask, if they care.

It was added as a result of an LWG issue; the meaning of the previous wording was unclear at best, with no explanation of what happened if the function failed to satisfy its stated postcondition. There is no general notion of “postcondition failure is an error”, but rather that “postcondition failure in the absence of a reported error is logically impossible”.

Since the initial version of this answer, a paper was accepted that changed it to be an error if and only if the conflicting object is not a directory, requiring a subsequent check on many platforms. This is unusual for C++, but the result was thought to be more intuitive and the operation is relatively expensive anyway.

Regardless, the reason your implementation fails on . would seem to be that it’s buggy. (I don’t have any special hints about how to most easily obtain a newer version.)

like image 85
Davis Herring Avatar answered Nov 14 '22 23:11

Davis Herring