Используя файловую систему:: path, как вы открываете файл кросс-платформенным способом?

Скажем, вы использовали новый код std::filesystem (или std::experimental::filesystem) для поиска файла. У вас есть переменная path, которая содержит полное имя пути к этой переменной.

Как открыть этот файл?

Это может показаться глупым, но рассмотрим очевидный ответ:

std::filesystem::path my_path = ...;
std::ifstream stream(my_path.c_str(), std::ios::binary);

Это не гарантируется. Зачем? Например, в Windows, path::string_type есть std::wstring. Поэтому path::c_str вернет a const wchar_t*. И std::ifstream может принимать только пути с типом const char*.

Теперь выясняется, что этот код действительно будет работать в VS. Зачем? Поскольку Visual Studio имеет расширение библиотеки которое позволяет это работать. Но это нестандартное поведение и, следовательно, не переносимое. Например, я понятия не имею, поддерживает ли GCC в Windows ту же функцию.

Вы можете попробовать следующее:

std::filesystem::path my_path = ...;
std::ifstream stream(my_path.string().c_str(), std::ios::binary);

Только Windows снова путает нас. Потому что, если my_path содержит символы Unicode, то теперь вы полагаетесь на правильную настройку языка Windows ANSI. И даже это не обязательно спасет вас, если в пути произойдут символы из нескольких языков, которые не могут существовать в одном и том же локали ANSI.

У файловой системы Boost действительно была аналогичная проблема. Но они расширили свою версию iostreams, чтобы поддерживать path напрямую.

Я что-то упустил? Помог ли комитет добавить межплатформенную библиотеку файловой системы, не добавляя кросс-платформенный способ открытия в нем файлов?

Ответы

Ответ 1

Бо Перссон отметил, что это тема отчета о дефекте стандартной библиотеки. Этот дефект был разрешен, и С++ 17 отправит, требуя реализации, где path::value_type не char, чтобы их типы потоков файлов принимали const filesystem path::value_type* в дополнение к обычным версиям const char*.