将 std::wstring 转换为 cstring 是否安全?

Is it safe to convert a std::wstring to cstring?

澄清一下,我并不过分担心数据丢失,因为这是为了在我的应用程序中记录操作,我' m 使用 wstring 作为主要数据类型。由于我目前使用的框架的性质(默认情况下 std::string 的 OpenFrameworks 日志记录,我可以接受)。

这是我当前转换的示例:

//ofLog.h--patch | `message` is a `std::ostringstream`
    ofLog& operator<<(const std::wstring& value){
        message << value.c_str() << padding;
        return *this;
    }

通过使用这个特定的重载,我可以在 Verbose 日志中省去很多烦恼,如果我有第三方 std::strings(OSC(char) 库与 JSON( wchar) 库)。

我对 C++ 比较陌生,我生活在 Java/JavaScript 的世界中,我只是想知道除了潜在的数据丢失之外是否还有其他风险。这个问题是否有独立于平台的解决方案?我已经在谷歌上搜索了几个小时,我想要一个 "safe" 解决方案,它不会让我陷入困境。

基本上我的解决方案似乎有效,但我想知道这样做是否存在潜在问题。

谢谢! (openframeworks 标签只是为了帮助大家解决问题)

编辑 如果有人需要这个用于 OpenFrameworks,以下似乎对我有用:

/*
ofLog.h
*/
        /// \brief Overload the wstring operator so that this actually works for 
        /// data of that format
        ///
        ofLog& operator<<(const std::wstring& value){
            std::string cvalue;
            std::transform(value.begin(), value.end(), 
                std::back_insert_iterator<std::string>(cvalue),
                [](wchar_t wide) 
                {
                    return static_cast<char>(wide > 127 ? '?' : wide);
                });

            message << cvalue << padding;
            return *this;
        }

        /// \brief Overloaded to support wchar_t * types
        ///
        /// 
        ofLog& operator<<(const wchar_t* value)
        {
            std::wstring wstr(value);
            std::string cvalue;
            std::transform(wstr.begin(), wstr.end(),
                std::back_insert_iterator<std::string>(cvalue),
                [](wchar_t wide)
            {
                return static_cast<char>(wide > 127 ? '?' : wide);
            });

            message << cvalue << padding;
            return *this;
        }
//END ofLog.h

显示的代码无法正常工作。 std::wstringc_str() 方法 returns 一个 const wchar_t *。将它传递给 std::ostringstreamoperator<< 将选择采用 const void * 参数的 operator<< 重载,这不会完成任何有用的事情。

您声明您希望 std::wstring 主要由 US-ASCII 字符组成。如果是这样,最 hackiest 的方法是按以下方式粗暴地将 std::wstring 转换为 std::string,将所有非 ASCII 字符替换为问号(或选择您喜欢的标点符号):

std::string cvalue;

std::transform(value.begin(), value.end(),
               std::back_insert_iterator<std::string>(cvalue),
               [](wchar_t wchar)
               {
                     return static_cast<char>(wchar > 127 ? '?':wchar);
               });

继续,<< 普通的 std::string 进入你的 message

如果您希望宽字符串主要由 US-ASCII 内容组成,这将是完成工作的快速技巧。否则,需要使用本地化库以使用当前系统区域设置将宽字符串正确转换为窄字符串。相当多的工作...