lazy facet instantiation

Howard Hinnant hhinnant@apple.com
Tue Nov 15 20:16:00 GMT 2005


On Nov 15, 2005, at 2:45 PM, Paolo Carlini wrote:

> Howard Hinnant wrote:
>
>> Has the locale implementation technique of "lazy facet instantiation"
>> been kicked around?  I searched the archive but came up empty.  Imho
>> this is a critical technique for reducing the code size triggered by
>> casual use of C++ I/O.
>
> [snip]
>
> The idea sounds very cool, of course. However, at the moment I don't
> fully understand where the *code size* (vs, application memory
> footprint) reduction comes from, at least not from a quick glance  
> to our
> locale from that point of view... Are you willing to explain in little
> more detail?

Sure.

All of the facets are templated.  Our current locale default  
constructor (somewhere deep down under) does something like:

install(new ctype<char>);
install(new ctype<wchar_t>);
install(new codecvt<char,...>);
install(new codecvt<wchar_t,...>);
install(new num_get<char>);
... etc. ...

So just the act of default constructing a locale instantiates all of  
the facets for all of the anticipated template parameters.

However if we instead of a locale default ctor that does nothing, and  
instead wait to fill the locale on an as-needed basis under  
use_facet<StandardFacet>(const locale&), then only those standard  
facets which are actually retrieved via a use_facet get installed  
into the locale.  The standard facets not explicitly called via a  
use_facet are not only not intalled into a locale, they aren't even  
instantiated (assuming client code doesn't explicitly instantiate them).

For example, HelloWorld might use just ctype and codecvt (that's just  
off the cuff, I'd have to study more to get a precise list).  This  
can cut the code size of HelloWorld (linked statically) by 80%.

It also affords one other really nice extension:  With this  
optimization a locale can contain a standard facet for an infinite  
variety of templates.  For example a locale would contain not only  
ctype<char> and ctype<wchar_t>, but could also contain ctype<C>,  
where C is any character-like type.  Support for such extensions  
allows clients to use basic_streams instantiated on types other than  
char and wchar_t.  All you have to do to use it is:

ctype<C>& ct = use_facet<ctype<C> >(some_locale);

(for some character-like type C).  The ctype<C> facet is instantiated  
*and* installed under the use_facet call.

This is a feature that both CodeWarrior and VC++ supports.  People  
want to do it, for example, when char is too small, and wchar_t is  
too big, they sometimes:

basic_ostringstream<unsigned short> os;

-Howard



More information about the Libstdc++ mailing list