Вот решение для систем POSIX, использующее open()
:
#include <fcntl.h> // open()
#include <unistd.h> // close()
fs::path unique_file(const fs::path &base, unsigned max_tries) {
fs::path p(base);
for(unsigned i = 1; i <= max_tries; ++i) {
// O_CREAT | O_EXCL will create the file if it does not exist, and fail otherwise
// 0666 : Read + Modify permissions for everybody
int fd = open(p.c_str(), O_CREAT | O_EXCL, 0666);
if(fd != -1) {
if(close(fd) == -1) // We immediately close the file, which might be a waste
throw fs::filesystem_error("unique_file: POSIX close() error", p, std::error_code(errno, std::generic_category()));
return p;
}
// EEXIST is set if open() failed because the file already existed
if(errno != EEXIST)
throw fs::filesystem_error("unique_file: POSIX open() error", p, std::error_code(errno, std::generic_category()));
errno = 0;
p = base.parent_path() / base.stem();
p += concatenate('_', i);
p += base.extension();
}
throw std::runtime_error("unique_file: gave up");
}
Windows, кажется, предлагает функцию _sopen_s
, которая предлагает та же комбинация _O_CREAT | _O_EXCL
флагов.