c ++ 11 — Не удается вставить число в пользовательский C ++ ostream / streambuf на основе char16_t

Я написал обычай std::basic_streambuf а также std::basic_ostream потому что я хочу выходной поток, из которого я могу получить строку JNI способом, подобным тому, как вы можете вызвать std::ostringstream::str(), Эти занятия довольно просты.

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) тривиально. Он просто удваивает ширину буфера, помещает запрошенный символ и правильно устанавливает указатели base, put и end. Это проверено, и я уверен, что это работает.

jni_utf16_ostream прекрасно работает вставка символов Юникода. Например, это работает нормально и приводит к потоку, содержащему «привет, мир»:

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 Мне нужно реализовать ????

0

Решение

Похоже, ответ таков char16_t поддержка реализована только частично в GCC 4.8. Заголовки библиотеки не устанавливают фасеты, необходимые для преобразования чисел. Вот что говорит об этом проект Boost.Locale:

GNU GCC 4.5 / C ++ 0x Status

Компилятор GNU C ++ обеспечивает достойную поддержку символов C ++ 0x:

Стандартная библиотека не устанавливает для этого никакой std :: locale :: facets
поддержка, поэтому любая попытка отформатировать числа с использованием char16_t или char32_t
потоки просто потерпят неудачу. Стандартная библиотека пропускает специализацию для
требуются фасеты char16_t / char32_t локали, поэтому бэкенды «std» не
возможность сборки, так как отсутствуют важные символы, также не может быть кодековский фасет
создано также.

Visual Studio 2010 (MSVC10) / C ++ 0x Status

MSVC предоставляет все необходимые аспекты, однако:

Стандартная библиотека не обеспечивает установки std :: locale :: id для
эти аспекты в DLL, поэтому он не может использоваться с флагами компилятора / MD, / MDd
и требует статической ссылки библиотеки времени выполнения. char16_t и char32_t
это не отдельные типы, а псевдонимы неподписанных коротких и
типы без знака, что противоречит требованиям C ++ 0x, что делает его
невозможно записать char16_t / char32_t в поток и вызвать несколько
разломы.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]