Bug 38196 - num_put<>::do_put(bool) performs 'internal' padding incorrectly when boolalpha==true
Summary: num_put<>::do_put(bool) performs 'internal' padding incorrectly when boolalph...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 4.4.0
Assignee: Paolo Carlini
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-11-20 10:54 UTC by Andrey Tsyvarev
Modified: 2008-11-20 16:02 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-11-20 13:42:27


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey Tsyvarev 2008-11-20 10:54:18 UTC
The description of num_put<>::do_put(bool) function states (22.2.2.2.2): 

iter_type do_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.

It is not specified how exactly the insertion the characters of s into out iterator is performed. It seems that the padding of the string is done the same way as for the other functions from num_put<>::do_put() family, namely (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), however, should output a string that in general is not a string representation of some number. It makes no sense for a string that can be arbitrary to process the sign symbols, "0x" or "0X" in a different way than its other substrings. That means, the 'internal' flag should be functionally equivalent to 'right' ("pad before") in this case. 

This is exactly the way the operator for inserting sequences of symbols into a stream (operator<< for const charT*) is implemented. Although the description of padding in this case (27.6.2.5.4, p2) refers to the description of num_put<>::do_put, in practice the 'internal' flag is functionally equivalent to 'right' in this case, which makes sense. 

However, the implementation of num_put<>::do_put(bool) performs 'internal' padding not like operator<< for sequences of characters but rather the same way as the other functions from num_put<>::do_put family: it inserts fill symbols between the 'sign' or "0x"/"0X" and the rest of the string.
Comment 1 Andrey Tsyvarev 2008-11-20 10:57:58 UTC
Example:

#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;
    return 0;
}

output "-  no-" instead of "  -no-"
Comment 2 Paolo Carlini 2008-11-20 13:42:27 UTC
Ok, let's do this.
Comment 3 paolo@gcc.gnu.org 2008-11-20 16:01:33 UTC
Subject: Bug 38196

Author: paolo
Date: Thu Nov 20 16:00:17 2008
New Revision: 142048

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=142048
Log:
2008-11-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/38196
	* include/bits/locale_facets.tcc (num_put<>::do_put(iter_type,
	ios_base&, char_type, bool)): Fix.
	* testsuite/22_locale/num_put/put/char/38196.cc: New.
	* testsuite/22_locale/num_put/put/wchar_t/38196.cc: Likewise.

Added:
    trunk/libstdc++-v3/testsuite/22_locale/num_put/put/char/38196.cc
    trunk/libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/38196.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/locale_facets.tcc

Comment 4 Paolo Carlini 2008-11-20 16:02:13 UTC
Fixed for 4.4.0.