я использую boost::lexical_cast<std::string>(double)
для преобразования значений типа double в строку, генерирования сериализованного байтового потока JSON, который (на удаленной стороне) анализируется .NET.
Я могу заставить .NET использовать InvariantCulture
для синтаксического анализа, тем самым возвращая предсказуемый результат на всех возможных языках.
Тем не менее, я не смог найти эту гарантию в повышение :: lexical_cast документация. Я попробовал это немного, и он работает одинаково для разных локалей. Но я не могу быть уверен только в нескольких тестах, я что-то упустил в документации или это вообще не может быть гарантировано, и я должен использовать что-то еще?
РЕДАКТИРОВАТЬ:
Я нашел проблему.
std::locale::global(std::locale("Czech"));
std::cout << boost::lexical_cast<std::string>(0.15784465) << std::endl;
возвращается 0,15784465
и это нежелательно. Могу ли я заставить boost::lexical_cast<>
не знать о локалях?
Могу ли я форсировать буст :: lexical_cast<> Не знать о локалях?
Нет, я не думаю, что это возможно. Лучшее, что вы можете сделать, это позвонить
std::locale::global(std::locale::classic());
установить глобальную локаль для локали «C» как boost::lexical_cast
зависит от глобальной локали. Однако проблема заключается в том, что если где-то еще в коде глобальная локаль установлена на что-то другое перед вызовом boost::lexical_cast
, тогда у вас все еще есть та же проблема.
Таким образом, надежное решение будет imbue
Строковый поток, как это, и вы всегда можете быть уверены, что это работает:
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss.precision(std::numeric_limits<double>::digits10);
oss << 0.15784465;
Лучшее решение этой проблемы — использовать повышение :: локаль вместо std :: locale как глобальной локали. От документация:
Установка глобальной локали имеет плохие побочные эффекты … она влияет даже на printf и такие библиотеки, как boost :: lexical_cast, которые дают неправильное или неожиданное форматирование. На самом деле многие сторонние библиотеки не работают в такой ситуации.
В отличие от стандартной библиотеки локализации, Boost.Locale никогда не меняет базовое форматирование чисел, даже если он использует бэкэнды локализации на основе std, поэтому по умолчанию числа всегда форматируются с использованием языкового стандарта в стиле C. Локализованное форматирование чисел требует определенных флагов.
Для повышения языкового стандарта необходимо явно указать, когда вы хотите, чтобы числовое форматирование учитывало языковой стандарт, что более соответствует последним решениям библиотеки, таким как std :: money_put.