std::put_money не выводит нулевое значение при использовании GCC

Когда денежное значение равно нулю, std::put_money не выводит символ '0', как ожидалось. Я не могу найти ничего, объясняющего такое поведение.

пример:

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

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

Я ожидаю, что на выходе будет 0,00 фунтов стерлингов (в зависимости от локали), но вместо этого я получаю 0,00 фунтов стерлингов.

В конечном счете, добавить особый случай для нулевых значений не так уж и сложно, но мне такое поведение все еще не имеет смысла. В чем причина этого (предполагая, что это преднамеренно) и, кроме отдельной обработки нуля, есть ли какие-либо простые обходные пути?

Обновлять

Это кажется специфичным для компилятора, у меня были отчеты о том, что он работает, как и ожидалось, с clang и VS, поэтому, вероятно, специфичен для gcc/g++ (точнее, версия 4.9, но другие версии, похоже, показывают такое же поведение)


person Jonny Paton    schedule 15.06.2017    source источник
comment
Я получаю 0,00 здесь (vs2017, windows 10).   -  person Rook    schedule 15.06.2017
comment
Да, просто обновляя OP - clang также выводит правильно, так что, похоже, это просто проблема gcc.   -  person Jonny Paton    schedule 15.06.2017
comment
Проблема существует и в gcc 6.3.   -  person Rosme    schedule 15.06.2017
comment
Подтверждено в GCC 6.3.0 с рядом языков (GB, US, DE, NO). Скорее всего проблема с библиотекой.   -  person Toby Speight    schedule 15.06.2017
comment
Я только что перебрал все локали, и мы видим это для каждой валюты, имеющей десятичный разделитель, но не для неразделенных валют, таких как иена: د.ت. .000 и ₪ .00, а ¥0 и ₩0.   -  person Toby Speight    schedule 15.06.2017
comment
Сообщите об ошибке gcc.gnu.org/bugs   -  person Jonathan Wakely    schedule 20.06.2017
comment
Теперь это gcc.gnu.org/bugzilla/show_bug.cgi?id=81138.   -  person Jonathan Wakely    schedule 20.06.2017


Ответы (1)


Хотя сначала я думал, что это выглядит как ошибка GCC, теперь я думаю, результат, который вы получаете от GCC std::lib, точно соответствует стандарту, если вы внимательно его прочитали.

Сначала количество преобразуется из long double в узкую строку символов с помощью спецификатора формата printf "%.0Lf", что дает "0". Это преобразуется в строку широких символов (что ничего не делает для вашего примера, поскольку вывод представляет собой узкий поток символов).

Затем вывод форматируется в соответствии с шаблоном форматирования локали moneypunct<>::pos_format() или moneypunct<>::neg_format() в зависимости от того, начинается ли строка со знака минус или нет.

Затем:

Цифровые символы записываются с вкраплениями любых разделителей тысяч и десятичной точки, указанных в формате, в том порядке, в котором они появляются (после необязательного ведущего знака минус).

Это ничего не говорит о добавлении начального нуля.

Я думаю, что предполагаемое поведение недоопределено стандартом. https://wg21.link/LWG2983 разъяснит это.

person Jonathan Wakely    schedule 21.06.2017
comment
Я согласен, что стандарт может быть более ясным, но в то же время я также думаю, что если вы применяете здравый смысл, то начальный 0 всегда должен быть там, точно так же, как при форматировании числа с плавающей запятой или двойного числа. Независимо от этого, если это не проблема в gcc, то это проблема в других компиляторах. - person Jonny Paton; 23.06.2017