I'm unsuccessfully trying to strip grouping (thousands separator) from std::locale.
I need to strip it from locale set in OS (for example sk_SK locale) but retain all others locale dependent formatting characteristics (decimal separator, etc).
Some of my attempts are in the code bellow. Looks like combining locale with no_separator strip all numpunct characteristics and reset them all back to "C" locale, instead of modifying just do_grouping characteristic.
(Windows10, VS, SDK 10.0, MSVC v142)
#include <iostream>
#include <locale>
#include <sstream>
struct no_separator : std::numpunct<char>
{
protected:
virtual string_type do_grouping() const
{
return "\0";
} // groups of 0 (disable)
};
int main()
{
std::cout.precision(8);
std::cout.width(12);
std::cout << "Test \"C\": " << 1234.5678 << std::endl; // OK - 1234.5678
std::locale skSKLocale("sk_SK");
std::cout.imbue(skSKLocale);
std::cout << "Test skSK: " << 1234.5678 << std::endl; // OK - 1 234,5678
//std::locale::global(skSKLocale);
std::locale localeNoThousandsSeparator = std::locale(skSKLocale, new no_separator());
std::locale finishedLoc = skSKLocale.combine<std::numpunct<char>>(localeNoThousandsSeparator);
std::cout.imbue(localeNoThousandsSeparator);
std::cout << "Test localeNoThousandsSeparator: " << 1234.5678 << std::endl; // BAD - expected 1234,5678, got 1234.5678
std::cout.imbue(finishedLoc);
std::cout << "Test finishedLoc: " << 1234.5678 << std::endl; // BAD - expected 1234,5678, got 1234.5678
}
Thank you for your help.
Your facet has no idea about the sk locale. It just uses the default implementation. You may want to forward all other methods of your custom numpunct
to the relevant facet of whatever locale you are modifying, something like:
struct no_separator : std::numpunct<char>
{
no_separator(std::locale& base_locale) :
np(std::use_facet< std::numpunct<char> >(base_locale)) {
}
protected:
string_type do_grouping() const override { return ""; }
char_type do_decimal_point() const override { return np.decimal_point(); }
char_type do_thousands_sep() const override { return np.thousands_sep(); }
string_type do_truename() const override { return np.truename(); }
string_type do_falsename() const override { return np.truename(); }
const std::numpunct<char> & np;
};