Как мне написать фасет std::codecvt?
Как мне написать фасет std::codecvt? Я хотел бы написать те, которые идут от UTF-16 до UTF-8, которые идут от UTF-16 до текущей кодовой страницы системы (windows, поэтому CP_ACP), и к системной кодовой странице OEM (windows, так CP_OEM).
Кроссплатформенность предпочтительнее, но MSVC в Windows тоже подойдет. Существуют ли какие-либо учебные пособия или что-то в этом роде о том, как правильно использовать этот класс?
2 ответа
Я написал один на основе iconv. Его можно использовать в Windows или в любой операционной системе POSIX. (Вам нужно будет связаться с iconv, очевидно).
Ответ на вопрос "как сделать" состоит в том, чтобы следовать ссылке codecvt. Два года назад мне не удалось найти более качественные инструкции в Интернете.
Важные уведомления
- теоретически нет необходимости в такой работе. codecvt_byname должно быть достаточно на любой стандартной платформе поддержки. Но на самом деле есть некоторые компиляторы, которые не поддерживают или плохо поддерживают этот класс. Существует также разница в интерфейсах codecvt_byname на разных компиляторах.
- Мой рабочий пример реализован с параметром шаблона состояния codecvt. Всегда используйте стандартный тип mbstate, так как это единственный способ использовать ваш codecvt со стандартными классами iostream.
- Тип std::mbstate_t нельзя использовать в качестве указателя на 64-битных платформах кроссплатформенным способом.
- Преобразования без сохранения состояния работают для коротких строк, но могут потерпеть неудачу, если вы попытаетесь преобразовать блок данных больше, чем размер внутреннего буфера streambuf (UTF - это, по сути, кодировка с состоянием)
Проблема с этим std::codecvt в том, что это решение ищет проблему. Или, скорее, проблема, которую он пытается решить, неразрешима, поэтому любой, кто попытается использовать его в качестве решения, будет очень разочарован.
Если вы не знаете, какой набор символов используется для ввода или вывода, std::codecvt никогда не сможет вам помочь. И наоборот, если вы знаете, какие наборы символов вы используете, то вы можете тривиально преобразовать их в один вызов функции. Оборачивание этого вызова функции в сложную путаницу шаблонов не меняет этих основ.
... и поэтому никто не использует std::codecvt. Я рекомендую вам просто делать то, что делают все остальные, и притворяться, что этого не произошло.