I would like to format prices in C++
I can use std::put_money
but the problem is that my number format locale is different from my currency locale.
Say I want to format a price in GBP in French, if I set the locale to French, I get a euro sign. I need the decimal in the user's locale and the currency in the price locale.
I can do that in Java with NumberFormat coming from the decimal locale and then setting the currency I want on it.
Can this be done in C++?
You can create your own moneypunct
facet, inheriting from std::moneypunct
, and construct a locale using it. Here's such facet you can construct from two locale names. One is responsible for the currency symbol and the other is for everything else.
template <class CharT, bool International = false>
class my_moneypunct;
template <class CharT, bool International = false>
class my_moneypunct_byname : public std::moneypunct_byname<CharT, International>
{
friend class my_moneypunct<CharT, International>;
using std::moneypunct_byname<CharT, International>::moneypunct_byname;
};
template <class CharT, bool International>
class my_moneypunct : public std::moneypunct_byname<CharT, International>
{
my_moneypunct_byname<CharT, International> other_moneypunct;
public:
explicit my_moneypunct(const char* myName, const char* otherName, std::size_t refs = 0) :
std::moneypunct_byname<CharT, International>(myName, refs), other_moneypunct(otherName, refs) {}
typename std::moneypunct_byname<CharT, International>::string_type do_curr_symbol() const override {
return other_moneypunct.do_curr_symbol();
}
virtual ~my_moneypunct() = default;
};
You can use it this way:
std::moneypunct<char>* mp = new_moneypunct<char>("en_GB.UTF-8", "fr_FR.UTF-8");
// or std::moneypunct<char>* mp = new_moneypunct<char>("fr_FR.UTF-8", "en_GB.UTF-8");
std::locale newloc(std::locale(), mp);
std::cout.imbue(newloc);
std::cout << std::showbase << std::put_money("1234567");
// prints '€12,345.67' or '12 345,67 £'
Note this is not tested for memory leaks.
You also can, instead of inheriting std::moneypunct_byname
, inherit just std::moneypunct
and forward every overridable method to different moneypunct
facets you fetch from several locales using std::use_facet
. Or hard code your currency symbol, or any other way you like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With