更改窄字符串编码或缺少std :: filesystem :: path :: imbue

时间:2017-03-13 13:44:16

标签: c++ utf-8 filepath c++17 boost-filesystem

我在Windows上,我正在std::filesystem::path构建std::string。根据构造函数引用(强调我的):

  

如果源字符类型为char,则源的编码将被假定为本机窄编码(因此不会在POSIX系统上进行转换)

如果我理解正确,这意味着字符串内容将被视为在Windows下以ANSI编码。要将其视为以UTF-8编码,我需要使用std::filesystem::u8path()函数。请参阅演示:http://rextester.com/PXRH65151

我希望path的构造函数将窄字符串的内容视为UTF-8编码。对于boost::filesystem::path,我可以使用imbue()方法执行此操作:

boost::filesystem::path::imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16<wchar_t>()));

但是,我在std::filesystem::path中没有看到这样的方法。有没有办法为std::filesystem::path实现这种行为?或者我是否需要在所有地方吐出u8path

2 个答案:

答案 0 :(得分:1)

出于性能考虑,path没有全局方式来定义区域设置转换。由于C ++ 11没有UTF-8字符串的特定类型,因此系统假定任何char字符串都是窄字符串。因此,如果您想使用UTF-8字符串,则必须通过向构造函数提供适当的转换区域设置或使用u8path来明确拼写它。

答案 1 :(得分:0)

我对此问题的解决方案是将std::filesystem完全别名为名为std::u8filesystem的不同命名空间,其中的类和方法将std::string视为UTF-8编码。类继承具有相同名称的std::filesystem中的对应项,而不添加任何字段或虚方法来提供完整的API / ABI互操作性。概念代码here的完整证明,仅在Windows上进行了测试,目前为止还远未完成。以下代码段显示了帮助程序的核心工作:

std::wstring U8ToW(const std::string &string);

namespace std
{
    namespace u8filesystem
    {

    #ifdef WIN32
        class path : public filesystem::path
        {
        public:
            path(const std::string &string)
                : fs::path(U8ToW(path))
            {
            }

            inline std::string string() const
            {
                return filesystem::path::u8string();
            }
        }
    #else
        using namespace filesystem;
    #endif
    }
}