Kalle Olavi Niemitalo writes:
Sam Varshavchik <mrsam@xxxxxxxxxxxxxxx> writes:I don't understand the logic I'm seeing with libstdc++'s instantiation of the time_put facet from a locale, and then using the facet to format a date into an ostream. It appears that time_put's locale gets ignored. The locale that's imbued in the ostream governs formatting of date/time localized strings.I don't have the C++ standard at hand but Josuttis says in "The C++ Standard Library" (1999) that std::time_put::put can access other locale facets via its ios_base parameter. That is what
The same wording is present in 2003.
happens with libstdc++: in <bits/locale_facets_nonio.tcc>, put and do_put access the non-standard std::__timepunct facet of the locale imbued in the ios_base, and call that to do the actual formatting. When you extract just the std::time_put facet of the fr_FR.utf-8 locale and tell that to use an ios_base imbued with
Well, that's all I need to do, as far as I know, to format the time and date: extract the std::time_put facet. Aside from using the C library functions that use the global C locale, how else can I format a localized date and time?
the C locale, std::time_put::put then finds the std::__timepunct facet of the C locale, and the output is not in French.
I understand the general reason for using the imbued locale. std::time_get::get, for example, may need to convert characters to lowercase. It makes sense, in this case then, to get the ctype category facet from the imbued locale. I see the reason for that.
This is what confuses me. It looks like it doesn't matter at all from which locale the std::time_put facet was retrieved from. The formatted output depends solely on the imbued locale. I can just grab a std::time_put facet anywhere I find one, and use it to format localized date and time strings in different locales.
Or, putting it differently: is there anything that std::time_put::do_put() does that it obtains from its own locale? I can't see anything. What's the reason that std::time doesn't take the std::__timepunct facet from its own locale, but gets it from the imbued one.
I suppose the standard permits this behaviour. It does seem inconvenient though if you want to construct a locale by mixing and matching facets from different locales, because you cannot know in advance which non-standard facets e.g. std::time_put will need in each implementation of the standard C++ library.
Yes, rereading the standard does seem to suggest it. A lot of the localization stuff is specified as implementation defined. Bummer.
However, if you only want to use a specific locale for a few output operations, then I think the best option is to construct a separate std::ios object, just for imbuing it with the desired locale and then passing it to time_put: std::ios format(std::cout.rdbuf()); format.copyfmt(std::cout); format.imbue(l); t.put(std::ostreambuf_iterator<char>(std::cout), format, ' ', &tmbuf, fmt, fmt+strlen(fmt));
Where did I get t from? Is t l's facet, or any random std::locale's facet?
Attachment:
pgpbr2e5AQGVH.pgp
Description: PGP signature