[lexical_cast] locale dependent result? (was: [lexical_cast] locale dependent result?)

No response on the boost.user list so I'm trying here in case the devs know: Is the result of lexical_cast<std::string> locale-dependent? One of my contributors has submitted a fix for a problem he says is caused by lexical_cast adding commas to a port number, e.g.: 65535 becomes "65,535". I'm unable to reproduce this but it may be something specific to his locale. If this is the case, what would be the correct way to get a canonical, locale-independent string from an integer? Thanks. Alex -- Easy SFTP for Windows Explorer (http://www.swish-sftp.org)

On 02/03/2011 13:00, Alexander Lamaison wrote:
If this is the case, what would be the correct way to get a canonical, locale-independent string from an integer?
You could use construe_cast, which uses Spirit instead of C++ iostreams. It is also much faster.

On Wed, 02 Mar 2011 13:13:13 +0100, Mathias Gaunard wrote:
On 02/03/2011 13:00, Alexander Lamaison wrote:
If this is the case, what would be the correct way to get a canonical, locale-independent string from an integer?
You could use construe_cast, which uses Spirit instead of C++ iostreams. It is also much faster.
Is this going to make an appearance in Boost any time soon? It looks very promising but I can't afford another dependency on non-boost code. Alex -- Easy SFTP for Windows Explorer (http://www.swish-sftp.org)

Is the result of lexical_cast<std::string> locale-dependent? One of my contributors has submitted a fix for a problem he says is caused by lexical_cast adding commas to a port number, e.g.: 65535 becomes "65,535".
I'm unable to reproduce this but it may be something specific to his locale.
Yes it is, It is easily reproducible: // under Linux std::locale::global(std::locale("en_US.UTF-8")); // under Windows + Visual Studio std::locale::global(std::locale("English_USA")); std::string ss=boost::lexical_cast<std::string>(65535);
If this is the case, what would be the correct way to get a canonical, locale-independent string from an integer?
Thanks.
Alex
If you want to do casting without locale context (which is desirable) std::ostringstream ss; ss.imbue(std::locale::classic()); // C locale ss << 65535; return ss.str(); Unfortunately this problem is very common and causes many bugs, especially in C with setlocale and printf. Artyom

On Wed, 2 Mar 2011 04:54:46 -0800 (PST), Artyom wrote:
Is the result of lexical_cast<std::string> locale-dependent? One of my contributors has submitted a fix for a problem he says is caused by lexical_cast adding commas to a port number, e.g.: 65535 becomes "65,535".
[..]
If you want to do casting without locale context (which is desirable)
std::ostringstream ss; ss.imbue(std::locale::classic()); // C locale ss << 65535; return ss.str();
Thanks! So std::locale::classic effectively means 'turn locale awareness off'?
Unfortunately this problem is very common and causes many bugs, especially in C with setlocale and printf.
I can imagine! It's so subtle and unexpected. In fact, I used lexical_cast precisely because I thought it wouldn't do anything funky with the conversion. At least that's how I interpreted the documentation: "For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional stringstream approach is recommended." Alex -- Easy SFTP for Windows Explorer (http://www.swish-sftp.org)

If you want to do casting without locale context (which is desirable)
std::ostringstream ss; ss.imbue(std::locale::classic()); // C locale ss << 65535; return ss.str();
Thanks! So std::locale::classic effectively means 'turn locale awareness off'?
It installs default so called "C" or "POSIX" locale that is what you need.
Unfortunately this problem is very common and causes many bugs, especially in C with setlocale and printf.
I can imagine! It's so subtle and unexpected. In fact, I used lexical_cast precisely because I thought it wouldn't do anything funky with the conversion.
It is not about lexical cast only it is about anything that uses iostream and *printf/*scanf/ato* and many other library functions. I recently seen how C (and C++) SQL libraries being broken because of global locale.
At least that's how I interpreted the documentation: "For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional stringstream approach is recommended."
The best is unfortunatly is avoid installing std::locale global using standard C++ localization, in fact because of this problem in Boost.Locale the default is to use C locale. i.e. ss << 65536; ss.str() == "65536"; And if you need localized numbers: ss << boost::locale::as::number ss.str() == "65,536" Because too many libraries become broken by this "feature" as std::locale::global(std::locale("de_DE.UTF-8")); std::ostringstream ss; ss << 12345.345; Would create "12.345,345" and printf("%f\n",12345.345); Would generate 12345,345 // <-- note "," and not "." So imagine how many libraries and programs do not work in such setups :-) Artyom
participants (3)
-
Alexander Lamaison
-
Artyom
-
Mathias Gaunard