无法在基于char16_t的自定义C ++ ostream / streambuf中插入数字

时间:2013-11-05 08:28:31

标签: c++ c++11 mingw iostream g++4.8

我编写了自定义std::basic_streambufstd::basic_ostream,因为我想要一个输出流,我可以通过类似于调用std::ostringstream::str()的方式获取JNI字符串。这些课很简单。

namespace myns {

class jni_utf16_streambuf : public std::basic_streambuf<char16_t>
{
    JNIEnv * d_env;
    std::vector<char16_t> d_buf;
    virtual int_type overflow(int_type);

public:
    jni_utf16_streambuf(JNIEnv *);
    jstring jstr() const;
};

typedef std::basic_ostream<char16_t, std::char_traits<char16_t>> utf16_ostream;

class jni_utf16_ostream : public utf16_ostream
{
    jni_utf16_streambuf d_buf;

public:
    jni_utf16_ostream(JNIEnv *);
    jstring jstr() const;
};

// ...

} // namespace myns

此外,我已经在operator<<进行了四次重载,所有重载都在同一名称空间中:

namespace myns {

// ...

utf16_ostream& operator<<(utf16_ostream&, jstring) throw(std::bad_cast);

utf16_ostream& operator<<(utf16_ostream&, const char *);

utf16_ostream& operator<<(utf16_ostream&, const jni_utf16_string_region&);

jni_utf16_ostream& operator<<(jni_utf16_ostream&, jstring);

// ...

} // namespace myns

jni_utf16_streambuf::overflow(int_type)的实施是微不足道的。它只是将缓冲区宽度加倍,放置请求的字符,并正确设置基本,放置和结束指针。经过测试,我确信它有效。

jni_utf16_ostream可以很好地插入unicode字符。例如,这样可以正常工作并生成包含“hello,world”的流:

myns::jni_utf16_ostream o(env);
o << u"hello, wor" << u'l' << u'd';

我的问题是,一旦我尝试插入一个整数值,流的坏位就会被设置,例如:

myns::jni_utf16_ostream o(env);
if (o.badbit()) throw "bad bit before"; // does not throw
int32_t x(5);
o << x;
if (o.badbit()) throw "bad bit after"; // throws :(

我不明白为什么会这样!在std::basic_streambuf上是否有其他方法我需要实现????

1 个答案:

答案 0 :(得分:1)

看起来答案是char16_t支持仅部分在GCC 4.8中实现。库头不会安装转换数字所需的构面。 Here is what the Boost.Locale project says about it

  

GNU GCC 4.5 / C ++ 0x状态

     

GNU C ++编译器提供了对C ++ 0x字符的不错支持:

     

标准库不为此安装任何std :: locale :: facets   支持使用char16_t或char32_t格式化数字的任何尝试   流只会失败。标准库错过了专业化   必需的char16_t / char32_t语言环境方面,所以“std”后端不是   可构建的基本符号缺失,也是codecvt facet不可能的   也创造了。

     

Visual Studio 2010(MSVC10)/ C ++ 0x状态

     

MSVC提供了所有必需的方面:

     

标准库不提供std :: locale :: id的安装   DLL中的这些方面因此不能与/ MD,/ MDd编译器标志一起使用   并需要运行时库的静态链接。 char16_t和char32_t   不是不同的类型,而是unsigned short和的别名   无符号类型与C ++ 0x要求相矛盾   不可能写char16_t / char32_t来流和导致多个   故障。