This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: PR 3983, basic_istringstream<unsigned char> fails
- From: Benjamin Kosnik <bkoz at redhat dot com>
- To: Craig Rodrigues <rodrigc at attbi dot com>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Mon, 25 Feb 2002 11:10:47 -0800 (PST)
- Subject: Re: PR 3983, basic_istringstream<unsigned char> fails
This issue keeps resurfacing in various forms. I should probably write
something up and put it in the 27_io FAQ.
Here's the first discussion:
2001-12-03
_M_fill initialization in basic_ios::init
http://gcc.gnu.org/ml/libstdc++/2001-12/msg00021.html
http://gcc.gnu.org/ml/libstdc++/2001-12/msg00106.html
http://gcc.gnu.org/ml/libstdc++/2001-12/msg00113.html
http://gcc.gnu.org/ml/libstdc++/2001-12/msg00120.html
Here's a recent patch that addressed this:
2002-01-24 Benjamin Kosnik <bkoz@redhat.com>
* include/bits/basic_ios.h (basic_ios::_M_check_facet): Make
const, tweak.
(basic_ios::fill(char_type)): Use fill().
* include/bits/basic_ios.tcc (basic_ios::widen): Use _M_check_facet.
(basic_ios::narrow): Same.
(basic_ios::_M_cache_facets): Explicitly set cached facets to zero
if they are invalid.
(basic_ios::init): Comment.
* testsuite/27_io/ios_init.cc (test02): New.
Here's the comment:
template<typename _CharT, typename _Traits>
void
basic_ios<_CharT, _Traits>::init(basic_streambuf<_CharT, _Traits>* __sb)
{
// NB: This may be called more than once on the same object.
ios_base::_M_init();
_M_cache_facets(_M_ios_locale);
_M_tie = 0;
// NB: The 27.4.4.1 Postconditions Table only specifies
// requirements after basic_ios::init() has been called. As part
// of this, fill() must return widen(' '), which needs an imbued
// ctype facet of char_type to return without throwing an
// exception. This is not a required facet, so streams with
// char_type != [char, wchar_t] will not have it by
// default. However, because fill()'s signature is const, this
// data member cannot be lazily initialized. Thus, thoughts of
// using a non-const helper function in ostream inserters is
// really besides the point.
_M_fill = this->widen(' ');
_M_exception = goodbit;
_M_streambuf = __sb;
_M_streambuf_state = __sb ? goodbit : badbit;
}
Here's the test:
// Non-required instantiations don't have the required facets inbued,
// by default, into the locale object. As such, basic_ios::init is
// required to return a bad_cast for the first use of fill() call.
// See 27.4.4.1
void test02()
{
bool test = true;
// 01: Doesn't call basic_ios::init, which uses ctype<char_type>..
try
{
std::basic_ostringstream<unsigned short> oss;
}
catch(...)
{
test = false;
}
// 02: Calls basic_ios::init, which uses ctype<char_type>..
try
{
std::basic_string<unsigned short> str;
std::basic_ostringstream<unsigned short> oss(str);
// Shouldn't get this far.
test = false;
// Try each member functions for unformatted io.
// put
oss.put(324);
// write
const unsigned short us[4] = {1246, 433, 520, 0};
oss.write(us, 4);
// flush
oss.flush();
}
catch(const std::bad_cast& obj)
{
test = true;
}
catch(...)
{
test = false;
}
VERIFY( test );
}
Basically, I don't see a way to make non-required facets work, given the
constraints imposed in the standard, as per above. I'm not quite sure if
this is a bug, or intentional. I might have also missed something: please
correct me if I'm wrong. I can ping the library list for clarificatin if
people think the unformatted input should really work with non-required
types.
-benjamin