Я могу подтвердить, что это не вопрос предварительных условий, и, по моему мнению, G CC прав, но я предполагаю, что разъяснение стандарта по этому вопросу было бы полезно.
Для В течение долгого времени довольно часто встречается способ помечать каталоги конечным разделителем, чтобы отличать guish от файлов. И я ожидал бы, что реализация std::filesystem::create_directories
вернет true, если путь, который должен быть создан, не существует до вызова и существует после вызова в результате вызова.
Давайте расширим пример немного:
#include <filesystem>
#include <iostream>
#include <system_error>
int main() {
std::error_code ec;
std::cout << std::boolalpha << std::filesystem::exists("a/b/c/") << "/";
std::cout << std::filesystem::create_directories("a/b/c/", ec) << "/";
std::cout << !!ec << "/" << std::filesystem::exists("a/b/c/");
}
Теперь мы можем использовать godbolt: https://godbolt.org/z/5883uY
И это показывает для GCC / libstdc ++ false/true/false/true
, как и следовало ожидать, это не существует, он был создан вызовом create_directories
, ошибки не было, и после этого он существует.
Теперь clang / libc ++ приводит к false/false/false/true
, поэтому его не существует, он сообщает мы не создали его, но сделали, ошибки нет, и мы доказали после вызова.
Если посмотреть на github-версию MSV C stl, похоже, она вызывает CreateDirectoryW
с: a
, a\b
, a\b\c
и, наконец, a\b\c\
, и этот последний сообщает ERROR_ALREADY_EXISTS
, что приводит к возвращению false
, как казалось, что мы ничего не делали, но я думаю, что это является реализацией детализации функции. Я предполагаю, что код Clang работает аналогично, но я еще не проверял источник libc ++.
И стандарт гласит: "Возвращает: true, если был создан новый каталог, иначе false. подпись с аргументом e c возвращает false, если возникает ошибка. "
Таким образом, стандарт хочет true
, если был создан каталог , а не последний, и для e c вариант false
сигнализирует об ошибке, но clang сообщает нам через ec
не было ни одного.
Я все еще могу ошибаться, поскольку я не в любом РГ, но мой вывод: G CC прав, и это похоже на ошибку в MSV C и Clang.
Как я уже собрал несоответствия между реализациями при проверке моего если я в порядке, я "с радостью" добавлю эту в свою коллекцию, если все в порядке.
Обновление: Я просто копался в других источниках, и Clang / libc ++ работает с рекурсивом * Механизм на основе 1051 *, который в итоге приводит к той же последовательности, что и MSV C, где t ::mkdir("a/b/c/")
предшествовал ::mkdir("a/b/c")
, поэтому он сообщает false, поскольку предполагает, что каталоги не создавались.