Подробности

[В начало]

Проблема в реализации № S0711

Краткое описание

num_put<>::do_put(bool) неверно выполняет 'internal' padding для случая boolalpha==true

Подробное описание

Из описания функции num_put<>::do_put(bool) (раздел 22.2.2.2.2):

iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const;

Effects: If (str.flags()&ios_base::boolalpha)==0 then do
out = do_put(out, str, fill, (int)val)

Otherwise do

const numpunct& np = use_facet<numpunct<charT> >(loc);
string_type s = val ? np.truename() : np.falsename();
and then insert the characters of s into out.


Примечание. "put" вместо "do_put" в сигнатуре функции - это опечатка, подробнее см. здесь

Не уточняется, как именно выполняется вставка символов строки s в итератор out. Судя по всему, заполнение строки (padding) до необходимой длины выполняется так же, как и для остальных функций семейства num_put<>::do_put() (22.2.2.2.2 p19 Table 61):

  • adjustfield == iosbase::left - pad after
  • adjustfield == iosbase::right - pad before
  • adjustfield == internal and a sign occurs in the representation - pad after the sign
  • adjustfield == internal and representation after stage 1 began with 0x or 0X - pad after x or X
  • otherwise pad before

Однако, num_put<>::do_put(bool) должен вывести строку, которая, в общем случае, не является строковым представлением числа. В таких строках выделение знака или сочетаний "0x" и "0X" лишено смысла. То есть в данном случае флаг 'internal' должен быть эквивалентен 'right' - "pad before".

Именно так реализован оператор вывода последовательности символов в поток (operator<< для const charT*). Хотя описание заполнения (padding) этой последовательности (27.6.2.5.4, p2) ссылается на num_put<>::do_put, на практике флаг 'internal' ведет себя также, как и 'right' в данном случае, что логично.

Однако реализация num_put<>::do_put(bool) при выполнении internal padding ведет себя так же, как и остальные функции семейства num_put<>::do_put - отделяет знак и сочетание "0x"/"0X" от остального содержимого строки.

В приведённом ниже примере выводится "-  no-", хотя должно быть выведено "  -no-".

Раздел стандарта

Linux Standard Base C++ Specification 3.2, Chapter 9. Libraries, 9.1. Interfaces for libstdcxx, который ссылается на ISO/IEC 14882: 2003 Programming languages --C++, section 22.2.2.2.2

Пример

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

class my_numpunct : public numpunct<char>
{
protected:
    string do_falsename() const {return "-no-";}
};

int main()
{
    locale my_loc = locale(locale::classic(), new my_numpunct());
    cout.imbue(my_loc);
    cout.width(6);
    bool b = false;

    cout << internal << boolalpha << b << endl;
    // "-  no-" is output instead of "  -no-"

    return 0;
}

Компонент

libstdc++

Принято

GCC Bugzilla 38196

Статус

Исправлено в gcc-4.4.0

[В начало]