This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: _M_fill initialization in basic_ios::init


On Fri, Dec 07, 2001 at 07:45:32AM +0000, Richard Burkert wrote:
> Paolo Carlini wrote:
>  >For instance, Langer/Kreft (0-201-18395-1), which I usually trust for 
>  >iostreams and locale issues (and is much more easier to read than the
>  >standard ;-) explicitly says at the beginning of chapter 5 that ctype
>  >is a *standard* facet, not a user-defined one, so it is "automatically
>  >contained in every locale".
> 
> Well it is a standard facet in that it's part of the set group
> of character facets predefined by the standard c++ library, but
> I don't think it's mandatory for two reasons that I can think
> of.  

The <char> and <wchar_t> instantiations are mandatory.  It is impossible 
to create a locale that has no ctype<char> facet.

> The first is just the fact that I don't think streams at
> their core should have to have anything to do with language or
> locales, since they can be useful for other types of data. So
> requiring locale facets for all stream element types would be
> pretty defeating for that whole area of stream application, or
> at the very least annoying, since you would have to manually
> define facets that you'd never actually use just to get the
> standard iostreams to work on a certain data type. 

A stream is a formatting or parsing service, which necessarily
depends on the locale.  If you have data that doesn't need either,
you probably should be using a streambuf and not an istream or
ostream.  How, otherwise, can the standard operators << discover 
what character to use for '0'?

> The ctype
> facet is for converting a stream element to and from char, I
> don't see at all why that should be a requirement for every
> type of stream element.

No, the ctype<> facet is to (1) tell you some facts about a character,
and (2) to convert to or from the native compile-time character set 
representation for the character, if it's in the "basic execution
character set" (which means, informally, any of the characters
that can appear in C++ source code).

>   The second reason is that the exist-
> ing libstdc++ code even indicates that all of the facets are
> optional. Take a look at _M_cache_facets from bits/basic_ios.tcc
> again:
> 
>   template<typename _CharT, typename _Traits>
>     void
>     basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc)
>     {
>       if (has_facet<__ctype_type>(__loc))
>     _M_ios_fctype = &use_facet<__ctype_type>(__loc);
>       // Should be filled in by ostream and istream, respectively.
>       if (has_facet<__numput_type>(__loc))
>     _M_fnumput = &use_facet<__numput_type>(__loc);
>       if (has_facet<__numget_type>(__loc))
>     _M_fnumget = &use_facet<__numget_type>(__loc);
>     }
> 
> It only caches each facet (note ctype first) -if- the locale
> supports that facet for whatever the stream element type. 

It checks if there is a ctype<_CharT> facet in case someone
constructs a stream instantiated on a non-standard character 
type with a locale that doesn't have a complete set of facets 
for that character type.  The behavior of such a program is
not defined.

> That's
> what it looks like to me at least, and at any rate it might not
> initialize _M_ios_fctype yet it calls a function from _M_ios_fctype
> no matter what (widen in init like i said before), so that
> doesn't seem right. If you wanted to require the ctype facet
> maybe assert that in _M_cache_facets instead of just conditionally
> initializing something which is later used unconditionally and
> letting it crash in the cases where it didnt have the facet.

If the facet's not there, the library can't do what you asked
it to do.  Probably it should set failbit in that case, instead
of crashing, though.
 
> I don't know, maybe even though there's contradictory code in
> basic_ios, they wanted all locales to support even the sort of
> null generic ctype so that wouldn't ever be a problem. Then the
> problem would be somewhere in the ctype or has_facet definitions
> in bits/locale_facets.*  Either way the code in basic_ios could
> use some clarifying I think.
> 
>  >So, please, come up with a self-contained seg-faulting testcase: it 
>  >will help focusing the real problem here.
> 
> Here you go:
> 
> #include <sstream>
> 
> int main () {
>   std::basic_stringstream<int> test;
>   return 0;
> }
> 
> ctype only has predefined specializations for char and wchar_t,
> so int just gets the generic version which apparently doesn't
> do it for whatever locale i'm in. See how it goes for you.

I would not expect constructing a stream to fail, because construction
is not defined in the standard to depend on any facet members.  I would
expect any formatted i/o operation to fail, though.  Crashing is a poor
way to fail in that case, but probably not explicitly nonconforming.

Nathan Myers
ncm at cantrip dot org


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]