Q about ctype.narrow

Pétur Runólfsson peturr02@ru.is
Tue Nov 25 17:38:00 GMT 2003


Jerry Quinn wrote:
> Here's the issue.  Assume we have ctype<char> that has been subclassed
> by a library client.  Now:
> 
> char ctype<char>::narrow(char c, char default)
> {
>   if (table[c]) return table[c];
>   return table[c] = do_narrow(c, default);
> }

I don't think this is allowed under the as-if rule. (Calling a virtual
function is an observable effect.)

[...]
> Fixing this starts to get uglier.  I think you need to detect that
> default may get returned and not cache the result in that case:
> 
> char ctype<char>::narrow(char c, char default)
> {
>   if (table[c]) return table[c];
>   char x = do_narrow(c, default);
>   if (x != default) table[c] = x;
>   return x;
> }

Is there any reason why the cache needs to be in ctype, rather than
in a separate class (like numpunct_cache)? Since the default is
usually known at compile time, something like this seems possible:

template<typename charT, char dfault>
class narrow_cache
{ 
  ctype<charT>* ct;
public:
  void init(ctype<charT>* f) { ct = f; }
  char narrow(charT c) const { return ct->narrow(c, dfault); }
};

template<char dfault>
class narrow_cache<char, dfault>
{
  ctype<charT>* ct;
  char narrow_table[256];
public:
  void init(ctype<charT>* f)
  {
    ct = f;
    for (int i = 0; i < 256; ++i)
      narrow_table[i] = ct->narrow(i, dfault);
  }
  char narrow(char c) const { return narrow_table[(unsigned char)c]; }
};

Then change

ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
if (__ctype.narrow(*__beg, 0) != '%')

to

narrow_cache<_CharT, '0'> const& __narrow_cache = ...;
if (__narrow_cache.narrow(*__beg) != '%')

This scheme also allows narrow to be cached for wchar_t. Since most
format strings passed to time_put::put only contain format
characters (such as %X %x %c %H etc.) it should be sufficient to
cache characters 0 to 128, and fall back to the virtual for higher
values:

char narrow(wchar_t c) const
{
  if (c < 128)
    return narrow_table[c];
  return ct->narrow(c, dfault);
}

(This obviously can't be done for the generic version, since character
types are not required to be convertible to integers.)

Regards,
Petur



More information about the Libstdc++ mailing list