[Bug libstdc++/115064] New: Possible problem with money_put
lcarreon at bigpond dot net.au
gcc-bugzilla@gcc.gnu.org
Mon May 13 07:14:11 GMT 2024
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115064
Bug ID: 115064
Summary: Possible problem with money_put
Product: gcc
Version: 14.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: lcarreon at bigpond dot net.au
Target Milestone: ---
I have been experimenting with std::money_put and discovered the following:
#include <locale>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <format>
int main()
{
std::locale loc{std::locale{"de_DE.utf8"}};
std::cout.imbue(loc);
auto money = 123456789.0L;
{
const auto& money_put =
std::use_facet<std::money_put<char>>(std::cout.getloc());
std::cout << "\"" << std::showbase << std::setw(20) << std::right;
money_put.put(std::cout, false, std::cout, '*', money);
std::cout << "\"" << std::endl;
}
{
std::ostringstream str;
str.imbue(loc);
const auto& money_put = std::use_facet<std::money_put<char>>(str.getloc());
str << std::showbase << std::setw(20) << std::right;
money_put.put(str, false, str, '*', money);
str << std::endl;
for (const auto& ch : str.str())
{
std::cout << std::format("{:02x} ", ch);
}
std::cout << std::endl;
}
return 0;
}
I compiled the above program using g++ 14.0.1 using c++20 mode. When I execute
the program on a terminal whose LANG is set to en_AU.utf8, I get the following
result:
"****1.234.567,89*€"
2a 2a 2a 2a 31 2e 32 33 34 2e 35 36 37 2c 38 39 2a e2 82 ac 0a
The first line above is the problematic one because it shows only 18 characters
inside the double quotes instead of 20. The second line above explains why.
The euro symbol is made up of three octets which is upsetting std::setw(20).
I revised the above program using wchar_t and std::wcout as follows:
#include <locale>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <format>
int main()
{
std::locale loc{std::locale{"de_DE.utf8"}};
std::wcout.imbue(loc);
auto money = 123456789.0L;
{
const auto& money_put =
std::use_facet<std::money_put<wchar_t>>(std::wcout.getloc());
std::wcout << L"\"" << std::showbase << std::setw(20) << std::right;
money_put.put(std::wcout, false, std::wcout, L'*', money);
std::wcout << L"\"" << std::endl;
}
{
std::wostringstream str;
str.imbue(loc);
const auto& money_put =
std::use_facet<std::money_put<wchar_t>>(str.getloc());
str << std::showbase << std::setw(20) << std::right;
money_put.put(str, false, str, L'*', money);
str << std::endl;
for (const auto& ch : str.str())
{
std::wcout << std::format(L"{:02x} ", static_cast<unsigned>(ch));
}
std::wcout << std::endl;
}
return 0;
}
Executing the above program on the same terminal, I get the following:
"******1.234.567,89*EUR"
2a 2a 2a 2a 2a 2a 31 2e 32 33 34 2e 35 36 37 2c 38 39 2a 20ac 0a
The first line above now has 22 characters instead of 20. The second line
above shows what characters were sent to the terminal. It seems the euro
symbol "20ac" is displayed by the terminal as "EUR" instead of the single glyph
"€".
I understand that the terminal is set for UTF-8, thus the correct display of
the euro symbol in char mode. But why display "EUR" in wchar_t mode?
More information about the Gcc-bugs
mailing list