Locales in Practice


The code examples we used in developing this article are compiled with VC++ v4.2 and the draft Standard C++ library that comes with it. This library does not conform completely to the draft C++ Standard, due to limitations in the VC++ v4.2 compiler.

For example, VC++ v4.2 does not support namespaces [VC++ v5.0 does — pjp]. We had to comment out the otherwise necessary using declaration, as in:

// using namespace std;

The locale names we used are necessarily those supported on Windows 95 and Windows NT.

VC++ v4.2 does not support explicit template argument specification. For this reason the standard interface for function templates like use_facet and has_facet cannot be implemented. The library that comes with VC++ 4.2 offers a workaround, which is shown below:

/* standard-conforming code:
    if (has_facet< ctype<char> >(locale::locale()))
    {  use_facet< ctype<char> >(locale::locale())
        .tolower(in.c_str(), in.c_str() + in.length());
        cout << in;
    }
*/
// workaround for vC++ 4.2

    if (_HAS(locale::locale(), ctype<char>))
    {  _USE(locale::locale(), ctype<char>)
        .tolower(in.c_str(), in.c_str() + in.length());
        cout << in;
    }
}

VC++ v4.2 does not support default template arguments [VC++ v5.0 does — pjp]. So we simplified the example and implemented the inserter only for tiny character streams of type ostream, instead of providing an inserter template, which would be natural. VC++ v4.2 does not support the standard interface of the time_put facet's put function [A bug — pjp]. we had to omit one of the arguments:

/* standard-conforming code:
template<class Ostream>
    Ostream& operator<<(Ostream& os,
        const struct tm& date)   
{
  typedef typename Ostream::char_type char_t;
  typedef typename Ostream::traits_type traits_t;
  typedef ostreambuf_iterator<char_t,traits_t> outIter_t;

  locale loc = os.getloc();
 
  const time_put<char_t,outIter_t>& fac =
     use_facet< time_put<char_t, outIter_t> >(loc);
     outIter_t nextpos = fac.put(os, os,
        os.fill(), &date, 'x');
  if (nextpos.failed())
    os.setstate(ios_base::badbit);
  return os;
}
*/
// simplified version for VC++ 4.2

ostream& operator<<(ostream& os,
    const struct tm& date)
{
    typedef ostream::char_type charType;
    typedef ostream::traits_type traitsType;
    typedef ostreambuf_iterator<charType, traitsType>
        outIter_t;
    typedef time_put<charType, outIter_t>
        time_put_facet_t;

    locale loc = os.getloc();
 
    const time_put<charType, outIter_t>& fac =
        _USE(loc,time_put_facet_t);

    outIter_t nextpos = fac.put(os, os,
        /* os.fill(), */ &date, 'x');
    if (nextpos.failed())
        os.setstate(ios_base::badbit);
    return os;
}