
Standard C++ Library Design Document
------------------------------------

This is an overview of libstdc++-v3, with particular attention
to projects to be done and how they fit into the whole.

The Library
-----------

This paper is covers two major areas:

 - Features and policies not mentioned in the standard that
   the quality of the library implementation depends on, including
   extensions and "implementation-defined" features;

 - Plans for required but unimplemented library features and
   optimizations to them.

Overhead
--------

The standard defines a large library, much larger than the standard
C library.  A naive implementation would suffer substantial overhead
in compile time, executable size, and speed, rendering it unusable
in many (particularly embedded) applications.  The alternative demands
care in construction, and some compiler support, but there is no
need for library subsets.

What are the sources of this overhead?  There are four main causes:

 - The library is specified almost entirely as templates, which
   with current compilers must be included in-line, resulting in
   very slow builds as tens or hundreds of thousands of lines
   of function definitions are read for each user source file.
   Indeed, the entire SGI STL, as well as the dos Reis valarray,
   are provided purely as header files, largely for simplicity in
   porting.  Iostream/locale is (or will be) as large again.

 - The library is very flexible, specifying a multitude of hooks
   where users can insert their own code in place of defaults.
   When these hooks are not used, any time and code expended to
   support that flexibility is wasted.

 - Templates are often described as causing to "code bloat".  In
   practice, this refers (when it refers to anything real) to several
   independent processes.  First, when a class template is manually
   instantiated in its entirely, current compilers place the definitions
   for all members in a single object file, so that a program linking
   to one member gets definitions of all.  Second, template functions
   which do not actually depend on the template argument are, under
   current compilers, generated anew for each instantiation, rather
   than being shared with other instantiations.  Third, some of the
   flexibility mentioned above comes from virtual functions (both in
   regular classes and template classes) which current linkers add
   to the executable file even when they manifestly cannot be called.

 - The library is specified to use a language feature, exceptions,
   which in the current gcc compiler ABI imposes a run time and
   code space cost to handle the possibility of exceptions even when
   they are not used.  Under the new ABI (accessed with -fnew-abi),
   there is a space overhead and a small reduction in code efficiency
   resulting from lost optimization opportunities associated with
   non-local branches associated with exceptions.

What can be done to eliminate this overhead?  A variety of coding
techniques, and compiler, linker and library improvements and
extensions may be used, as covered below.  Most are not difficult,
and some are already implemented in varying degrees.

Overhead: Compilation Time
--------------------------

Providing "ready-instantiated" template code in object code archives
allows us to avoid generating and optimizing template instantiations
in each compilation unit which uses them.  However, the number of such
instantiations that are useful to provide is limited, and anyway this
is not enough, by itself, to minimize compilation time.  In particular,
it does not reduce time spent parsing conforming headers.

Quicker header parsing will depend on library extensions and compiler
improvements.   One approach is some variation on the techniques
previously marketed as "pre-compiled headers", now standardized as
support for the "export" keyword.  "Exported" template definitions
can be placed (once) in a "repository" -- really just a library, but
of template definitions rather than object code -- to be drawn upon
at link time when an instantiation is needed, rather than placed in
header files to be parsed along with every compilation unit.

Until "export" is implemented we can put some of the lengthy template
definitions in #if guards or alternative headers so that users can skip
over the the full definitions when they need only the ready-instantiated
specializations.

To be precise, this means that certain headers which define
templates which users normally use only for certain arguments
can be instrumented to avoid exposing the template definitions
to the compiler unless a macro is defined.  For example, in
<string>, we might have:

   template <class _CharT, ... > class basic_string {
     ... // member declarations
   };
   ... // operator declarations

   #ifdef _STRICT_ISO_
   # if _G_NO_TEMPLATE_EXPORT
   #   include <bits/std_locale.h>  // headers needed by definitions
   #   ...
   #   include <bits/string.tcc>  // member and global template definitions.
   # endif
   #endif

Users who compile without specifying a strict-ISO-conforming flag
would not see many of the template definitions they now see, and rely
instead on ready-instantiated specializations in the library.  This
technique would be useful for the following substantial components:
string, locale/iostreams, valarray.  It would *not* be useful or
usable with the following: containers, algorithms, iterators,
allocator.  Since these constitute a large (though decreasing)
fraction of the library, the benefit the technique offers is
limited.

The language specifies the semantics of the "export" keyword, but
the gcc compiler does not yet support it.  When it does, problems
with large template inclusions can largely disappear, given some
minor library reorganization, along with the need for the apparatus
described above.

Overhead: Flexibility Cost
--------------------------

The library offers many places where users can specify operations
to be performed by the library in place of defaults.  Sometimes
this seems to require that the library use a more-roundabout, and
possibly slower, way to accomplish the default requirements than
would be used otherwise.

The primary protection against this overhead is thorough compiler
optimization, to crush out layers of inline function interfaces.
Kuck & Associates has demonstrated the practicality of this kind
of optimization.

The second line of defense against this overhead is explicit
specialization.  By defining helper function templates, and writing
specialized code for the default case, overhead can be eliminated
for that case without sacrificing flexibility.  This takes full
advantage of any ability of the optimizer to crush out degenerate
code.

The library specifies many virtual functions which current linkers
load even when they cannot be called.  Some minor improvements to the
compiler and to ld would eliminate any such overhead by simply
omitting virtual functions that the complete program does not call.
A prototype of this work has already been done.  For targets where
GNU ld is not used, a "pre-linker" could do the same job.

The main areas in the standard interface where user flexibility
can result in overhead are:

 - Allocators:  Containers are specified to use user-definable
   allocator types and objects, making tuning for the container
   characteristics tricky.

 - Locales: the standard specifies locale objects used to implement
   iostream operations, involving many virtual functions which use
   streambuf iterators.

 - Algorithms and containers: these may be instantiated on any type,
   frequently duplicating code for identical operations.

 - Iostreams and strings: users are permitted to use these on their
   own types, and specify the operations the stream must use on these
   types.

Note that these sources of overhead are _avoidable_.  The techniques
to avoid them are covered below.

Code Bloat
----------

In the SGI STL, and in some other headers, many of the templates
are defined "inline" -- either explicitly or by their placement
in class definitions -- which should not be inline.  This is a
source of code bloat.  Matt had remarked that he was relying on
the compiler to recognize what was too big to benefit from inlining,
and generate it out-of-line automatically.  However, this also can
result in code bloat except where the linker can eliminate the extra
copies.

Fixing these cases will require an audit of all inline functions
defined in the library to determine which merit inlining, and moving
the rest out of line.  This is an issue mainly in chapters 23, 25, and
27.  Of course it can be done incrementally, and we should generally
accept patches that move large functions out of line and into ".tcc"
files, which can later be pulled into a repository.  Compiler/linker
improvements to recognize very large inline functions and move them
out-of-line, but shared among compilation units, could make this
work unnecessary.

Pre-instantiating template specializations currently produces large
amounts of dead code which bloats statically linked programs.  The
current state of the static library, libstdc++.a, is intolerable on
this account, and will fuel further confused speculation about a need
for a library "subset".  A compiler improvement that treats each
instantiated function as a separate object file, for linking purposes,
would be one solution to this problem.  An alternative would be to
split up the manual instantiation files into dozens upon dozens of
little files, each compiled separately, but an abortive attempt at
this was done for <string> and, though it is far from complete, it
is already a nuisance.  A better interim solution (just until we have
"export") is badly needed.

When building a shared library, the current compiler/linker cannot
automatically generate the instantiatiations needed.  This creates a
miserable situation; it means any time something is changed in the
library, before a shared library can be built someone must manually
copy the declarations of all templates that are needed by other parts
of the library to an "instantiation" file, and add it to the build
system to be compiled and linked to the library.  This process is
readily automated, and should be automated as soon as possible.
Users building their own shared libraries experience identical
frustrations.

Sharing common aspects of template definitions among instantiations
can radically reduce code bloat.  The compiler could help a great
deal here by recognizing when a function depends on nothing about
a template parameter, or only on its size, and giving the resulting
function a link-name "equate" that allows it to be shared with other
instantiations.  Implementation code could take advantage of the
capability by factoring out code that does not depend on the template
argument into separate functions to be merged by the compiler.

Until such a compiler optimization is implemented, much can be done
manually (if tediously) in this direction.  One such optimization is
to derive class templates from non-template classes, and move as much
implementation as possible into the base class.  Another is to partial-
specialize certain common instantiations, such as vector<T*>, to share
code for instantiations on all types T.  While these techniques work,
they are far from the complete solution that a compiler improvement
would afford.

Overhead: Expensive Language Features
-------------------------------------

The main "expensive" language feature used in the standard library
is exception support, which requires compiling in cleanup code with
static table data to locate it, and linking in library code to use
the table.  For small embedded programs the amount of such library
code and table data is assumed by some to be excessive.  Under the
"new" ABI this perception is generally exaggerated, although in some
cases it may actually be excessive.

To implement a library which does not use exceptions directly is
not difficult given minor compiler support (to "turn off" exceptions
and ignore exception constructs), and results in no great library
maintenance difficulties.  To be precise, given "-fno-exceptions",
the compiler should treat "try" blocks as ordinary blocks, and
"catch" blocks as dead code to ignore or eliminate.  Compiler
support is not strictly necessary, except in the case of "function
try blocks"; otherwise the following macros almost suffice:

  #define throw(X)
  #define try      if (true)
  #define catch(X) else if (false)

However, there may be a need to use function try blocks in the
library implementation, and use of macros in this way can make
correct diagnostics impossible.  Furthermore, use of this scheme
would require the library to call a function to re-throw exceptions
from a try block.  Implementing the above semantics in the compiler
is preferable.

Given the support above (however implemented) it only remains to
replace code that "throws" with a call to a well-documented "handler"
function in a separate compilation unit which may be replaced by
the user.  The main source of exceptions that would be difficult
for users to avoid is memory allocation failures, but users can
define their own memory allocation primitives that never throw.
Otherwise, the complete list of such handlers, and which library
functions may call them, would be needed for users to be able to
implement the necessary substitutes.  (Fortunately, they have the
source code.)

Opportunities
-------------

The template capabilities of C++ offer enormous opportunities for
optimizing common library operations, well beyond what would be
considered "eliminating overhead".  In particular, many operations
done in Glibc with macros that depend on proprietary language
extensions can be implemented in pristine Standard C++.  For example,
the chapter 25 algorithms, and even C library functions such as strchr,
can be specialized for the case of static arrays of known (small) size.

Detailed optimization opportunities are identified below where
the component where they would appear is discussed.  Of course new
opportunities will be identified during implementation.

Unimplemented Required Library Features
---------------------------------------

The standard specifies hundreds of components, grouped broadly by
chapter.  These are listed in excruciating detail in the CHECKLIST
file.

  17 general
  18 support
  19 diagnostics
  20 utilities
  21 string
  22 locale
  23 containers
  24 iterators
  25 algorithms
  26 numerics
  27 iostreams
  Annex D  backward compatibility

Anyone participating in implementation of the library should obtain
a copy of the standard, ISO 14882.   People in the U.S. can obtain an
electronic copy for US$18 from ANSI's web site.  Those from other
countries should visit http://www.iso.ch/ to find out the location
of their country's representation in ISO, in order to know who can
sell them a copy.

The emphasis in the following sections is on unimplemented features
and optimization opportunities.

Chapter 17  General
-------------------

Chapter 17 concerns overall library requirements.

The standard doesn't mention threads.  A multi-thread (MT) extension
primarily affects operators new and delete (18), allocator (20),
string (21), locale (22), and iostreams (27).  The common underlying
support needed for this is discussed under chapter 20.

The standard requirements on names from the C headers create a
lot of work, mostly done.  Names in the C headers must be visible
in the std:: and sometimes the global namespace; the names in the
two scopes must refer to the same object.  More stringent is that
Koenig lookup implies that any types specified as defined in std::
really are defined in std::.  Names optionally implemented as
macros in C cannot be macros in C++.  (An overview may be read at
<http://www.cantrip.org/cheaders.html>).  The scripts "inclosure"
and "mkcshadow", and the directories shadow/ and cshadow/, are the
beginning of an effort to conform in this area.

A correct conforming definition of C header names based on underlying
C library headers, and practical linking of conforming namespaced
customer code with third-party C libraries depends ultimately on
an ABI change, allowing namespaced C type names to be mangled into
type names as if they were global, somewhat as C function names in a
namespace, or C++ global variable names, are left unmangled.  Perhaps
another "extern" mode, such as 'extern "C-global"' would be an
appropriate place for such type definitions.  Such a type would
affect mangling as follows:

  namespace A {
    struct X {};
    extern "C-global" {  // or maybe just 'extern "C"'
      struct Y {};
    };
  }
  void f(A::X*);  // mangles to f__FPQ21A1X
  void f(A::Y*);  // mangles to f__FP1Y

(It may be that this is really the appropriate semantics for regular
'extern "C"', and 'extern "C-global"', as an extension, would not be
necessary.) This would allow functions declared in non-standard C headers
(and thus fixable by neither us nor users) to link properly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem this solves is thatingent is troperly with functions
declared using C types defined in properly-namespaced headers.  The
problem