Давайте рассмотрим следующий код, перечисляющий содержимое каталога пути, указанного в качестве первого аргумента программы:
#include <filesystem>
#include <iostream>
int main(int argc, char **argv)
{
if(argc != 2)
std::cerr << "Please specify a directory.\n";
for(auto& p: std::filesystem::directory_iterator(argv[1]))
std::cout << p << '\n';
}
На первый взгляд это кажется очень компактным, переносимым и соответствующим стандарту C ++(пожалуйста, не обращайте внимания на то, что он не перехватывает исключения, если каталог не существует).
Однако, похоже, есть несколько подводных камней.В частности, стандарт C ++, по-видимому, не предписывает, что кодировка argv[1]
соответствует принятой конструкторами std::filesystem::path
, и не требует, чтобы кодировка, возвращаемая std::filesystem::path::string()
, совпадала с принятой std::cout
.
Скорее наоборот, стандарт, кажется, вводит новый термин «собственное кодирование», которое может отличаться от кодировки набора символов выполнения и определяется как:
Собственное кодирование узкогоСтрока символов - это текущая кодировка путей, зависящая от операционной системы ([fs.class.path]).
Из моего прочтения стандарта не происходит преобразования между кодировками, если std::filesystem::path::value_type
соответствует типу char
argv[1]
(что верно для любой системы POSIX).
Это, кажется, позволяет, например, соответствовать реализации, в которой кодирование набора символов выполнения (и, следовательно,кодировка argv[1]
и принятая std::cout
) является EBCDIC, но кодировка строк принята и предоставленаБиблиотека файловой системы соответствует стандарту ISO 8859-1, и между ними нет преобразования, что делает библиотеку файловой системы практически бесполезной. Хуже того, нет способа выяснить, одинаковы ли эти две кодировки.
Это может даже стать опасным, если вы начнете писать утилиты, которые удаляют файлы иУдаленный файл, предоставленный argv[1]
, соответствует совершенно другому файлу, если он интерпретируется в собственной кодировке библиотеки файловой системы.
Обратите внимание, что файловые системы не используют кодировки, отличающиеся от тех, которые используются программами.Меня беспокоит то, что стандарт, по-видимому, не требует какого-либо преобразования этих кодировок.
Функции u8path()
и u8string()
здесь также бесполезны, поскольку стандарт также не предоставляет способа преобразования между UTF-8 и кодировка набора символов выполнения (используется argv[1]
и std::cout
).
Существует ли какой-либо переносимый, независимый от кодирования и совместимый со стандартами способ сделать это?