std::put_money doesn't output zero value when using GCC
Asked Answered
B

1

6

When the monetary value is zero, std::put_money doesn't output the '0' character as expected. I can't find anything explaining this behaviour.

example:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    cout.imbue(locale(""));
    cout << showbase << put_money(0.0);
    return 0;
}

I would expect the output to be "£0.00" (dependant on locale) but instead I get "£.00"

Ultimately, it's not too troublesome adding a special case for zero values, but this behaviour still doesn't make sense to me. What's the reason for this (presuming it's intentional), and other than handling zero separately, are there any simple workarounds?

Update

This seems compiler specific, I've had reports that it works as expected with clang and VS, so probably gcc/g++ specific (version 4.9 to be precise, but other versions seem to show the same behaviour)

Bicker answered 15/6, 2017 at 14:13 Comment(7)
I get a 0.00 here (vs2017, windows 10).Abroach
Yes, just updating the OP - clang also outputs correctly, so seemingly just a gcc issueBicker
The issue is there also on gcc 6.3.Chasechaser
Confirmed in GCC 6.3.0 with a range of locales (GB, US, DE, NO). Likely a library issue.Hoecake
I've just iterated over all locales, and we see it for every currency that has a decimal separator, but not for non-subdivided currencies such as yen: د.ت. .000 and ₪ .00, but ¥0 and ₩0.Hoecake
Please report a bug gcc.gnu.org/bugsPendergrass
This is now gcc.gnu.org/bugzilla/show_bug.cgi?id=81138Pendergrass
P
0

Although I initially thought this looked like a GCC bug, I now think the result you get from GCC's std::lib is exactly what the standard requires, if you read it strictly.

First the quantity is transformed from long double to a narrow character string using the printf format specifier "%.0Lf", which produces "0". That is converted to a wide character string (which does nothing for your example as the output is to a narrow character stream).

Then the output is formatted according to the locale's moneypunct<>::pos_format() or moneypunct<>::neg_format() formatting pattern, according to whether the string begins with a minus sign or not.

Then:

Digit characters are written, interspersed with any thousands separators and decimal point specified by the format, in the order they appear (after the optional leading minus sign)

This says nothing about adding a leading zero.

I think the intended behaviour is underspecified by the standard. https://wg21.link/LWG2983 will clarify it.

Pendergrass answered 21/6, 2017 at 12:54 Comment(1)
I agree the standard could maybe be clearer, but at the same time I also think if you apply common sense then the leading 0 should always be there, just like when you format a float or double. Regardless of that, if it's not an issue in gcc, then it's an issue in the other compilersBicker

© 2022 - 2024 — McMap. All rights reserved.