C++ Xerces-c和跨平台字符串文本

C++ Xerces-c和跨平台字符串文本,c++,string,portability,xerces-c,C++,String,Portability,Xerces C,我正在将一个使用Xerces-c进行XML处理的代码库从Windows/VC++移植到Linux/G++ 在Windows上,Xerces-c使用wchar\u t作为字符类型XmlCh。这允许人们使用std::wstring和L”“语法的字符串文本 在Linux/G++上,wchar\u t是32位的,Xerces-c使用无符号短int(16位)作为字符类型XmlCh 我从这条轨道开始: #ifdef _MSC_VER using u16char_t = wchar_t; using u16s

我正在将一个使用Xerces-c进行XML处理的代码库从Windows/VC++移植到Linux/G++

在Windows上,Xerces-c使用
wchar\u t
作为字符类型
XmlCh
。这允许人们使用
std::wstring
L”“
语法的字符串文本

在Linux/G++上,
wchar\u t
是32位的,Xerces-c使用
无符号短int
(16位)作为字符类型
XmlCh

我从这条轨道开始:

#ifdef _MSC_VER
using u16char_t = wchar_t;
using u16string_t = std::wstring;
#elif defined __linux
using u16char_t = char16_t;
using u16string_t = std::u16string;
#endif
不幸的是,
char16\u t
unsigned short int
不是等价的,它们的指针不是隐式可转换的。因此,将
u“Hello,world.”
传递给Xerces函数仍然会导致无效的转换错误


看起来我必须显式地强制转换传递给Xerces函数的每个字符串。但在此之前,我想问一下是否有人知道一种更明智的方法来编写跨平台Xerces-c代码。

答案是没有,没有人知道如何做到这一点。对于其他发现这个问题的人,我想到的是:

#ifdef _MSC_VER
#define U16S(x) L##x
#define U16XS(x) L##x

#define XS(x) x
#define US(x) x

#elif defined __linux

#define U16S(x) u##x
#define U16XS(x) reinterpret_cast<const unsigned short *>(u##x)

inline unsigned short *XS(char16_t* x) {
    return reinterpret_cast<unsigned short *>(x);
}
inline const unsigned short *XS(const char16_t* x) {
    return reinterpret_cast<const unsigned short *>(x);
}
inline char16_t* US(unsigned short *x) {
    return reinterpret_cast<char16_t *>(x);
}
inline const char16_t* US(const unsigned short *x) {
    return reinterpret_cast<const char16_t*>(x);
}

#include "char16_t_facets.hpp"
#endif

namespace SafeStrings {
#if defined _MSC_VER

    using u16char_t = wchar_t;
    using u16string_t = std::wstring;
    using u16sstream_t = std::wstringstream;
    using u16ostream_t = std::wostream;
    using u16istream_t = std::wistream;
    using u16ofstream_t = std::wofstream;
    using u16ifstream_t = std::wifstream;
    using filename_t = std::wstring;

#elif defined __linux

    using u16char_t = char16_t;
    using u16string_t = std::basic_string<char16_t>;
    using u16sstream_t = std::basic_stringstream<char16_t>;
    using u16ostream_t = std::basic_ostream<char16_t>;
    using u16istream_t = std::basic_istream<char16_t>;
    using u16ofstream_t = std::basic_ofstream<char16_t>;
    using u16ifstream_t = std::basic_ifstream<char16_t>;
    using filename_t = std::string;

#endif
\ifdef\u MSC\u VER
#定义U16S(x)L##x
#定义U16XS(x)L##x
#定义XS(x)x
#定义我们(x)x
#elif已定义uu linux
#定义U16S(x)u##x
#定义U16XS(x)重新解释u型铸造(u##x)
内联无符号短*XS(char16_t*x){
返回重新解释(x);
}
内联常量无符号短*XS(常量char16_t*x){
返回重新解释(x);
}
内联字符16_t*US(无符号短*x){
返回重新解释(x);
}
内联常量char16_t*US(常量无符号短*x){
返回重新解释(x);
}
#包括“char16_t_facets.hpp”
#恩迪夫
命名空间安全字符串{
#如果已定义,则为MSC版本
使用u16char\u t=wchar\u t;
使用u16string\u t=std::wstring;
使用u16sstream_t=std::wstringstream;
使用u16ostream_t=std::wostream;
使用u16istream\u t=std::wistream;
使用u16ofstream_t=std::wofstream;
使用u16ifstream\u t=std::wifstream;
使用文件名\u t=std::wstring;
#elif已定义uu linux
使用u16char\u t=char16\u t;
使用u16string\u t=std::basic\u字符串;
使用u16sstream\u t=std::basic\u stringstream;
使用u16ostream\u t=std::basic\u ostream;
使用u16istream\u t=std::basic\u istream;
使用u16ofstream_t=std::basic_of stream;
使用u16ifstream\u t=std::basic\u ifstream;
使用文件名\u t=std::string;
#恩迪夫
char16\u t\u facets.hpp
具有模板专业化的定义
std::ctype
std::numpunt
std::codevt
。有必要将其与
std::num_get
std::num_put
一起添加到全局区域设置中(但无需为这些提供专业化)。编解码器VT的代码是唯一困难的部分,在GCC 5.0库中可以找到一个合理的模板(如果您使用GCC 5,您不需要提供编解码器VT专业化,因为它已经在库中)

完成所有这些操作后,
char16\t
流将正常工作

然后,每次定义宽字符串时,而不是
L“string”
,都要写
U16S(“string”)
。每次将字符串传递给Xerces时,都要写XS(string.c_str())或U16XS(“string”)作为文本。每次从Xerces取回字符串时,都要将其转换回
u16string_t(US(调用Xerces函数())

请注意,也可以将字符类型设置为char16_t来重新编译Xerces-C。这将省去上面所需的大量工作。但是您将无法使用系统上任何其他依赖Xerces-C的库。链接到任何此类库都将导致链接错误(因为更改字符类型会更改许多Xerces函数签名)