             ===================================================
             InitUtil.h: An STL Container Initialization Library
             ===================================================

                                 Leor Zolman
                                 BD Software
                               leor@bdsoft.com
         www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix

            InitUtil web page: www.bdsoft.com/tools/initutil.html

===============================================================================
NOTE: There are now 3 versions of this library to choose from. To get the most
      functionality, use the highest-numbered version supported by your 
      platform:

Version 2.x:    (This version)
                Most advanced version: supports a simplified calling syntax,
                implemented with the aid of operator conversion objects.
                Requires the most compiler/library conformance.

                Works (so far) with  MSVC 7.1 (stock lib and Dinkum Unabridged
                Library), Comeau 4.3 (libcomo and Dinkum Unabridged Library),
                gcc 3.2, Intel 7/8.

                Notes:
                    Use /GX with MSVC 7.1/stock lib to suppress EH warnings.
                    Use /Za with MSVC 7.1/stock lib if using hash-based con-
                        tainers.

                    If using the Dinkum Unabridged Library, see the bug note
                    in the file Dinkum.txt (affects hash-based containers).

                    Under Intel 7/8, only test2.cpp only compiles with 
                        #define HASHED_CONTAINERS_SUPPORTED 0
                    at the top of the file (after initial comments).

Version .92x:   Runs on MSVC 7.1, gcc 3, CodeWarrior 7/8, Intel 7, Comeau.
                Supports associative and hashed containers, and eliminates the
                need for separately-named "_str" functions by specializing
                make_cont for string containers. However, this version
                requires better compiler support than .91 does.


Version .91xms: Runs on MSVC 6/7/7.1, gcc 3, CodeWarrior 7/8, Intel 7, Comeau.
                Supports the STL sequence containers only (vector, deque, list).
===============================================================================


Version 2.0 Initial Release: January 25, 2004 (see initutil2-log.txt for change
log)

To use these facilities, simply include "InitUtil.h" in your programs
In the distribution archive, the test program test2.cpp demonstrates many
of the variations. The other header files are there just in support of the
test program (e.g., ESTLUtil.h provides some useful utilities for displaying
the contents of a container.)

-------------------------------------------------------------------------
Note: If your platform does NOT support hash-based containers, then to run
the test program (test2.cpp) you must place the following line at the top
of it:

    #define HASHED_CONTAINER_SUPPORT 0
-----------------------------------------------------------------------



Description:
============

STL containers are a pain to initialize with constant values. One
approach is to create a plain old array and use it to initialize
the container, as in:

    int vals[] = { 10, 20, 100, -30, 0, -50, 999, 22 };
    const size_t size = sizeof vals / sizeof vals[0];
    vector<int> v(vals, vals + SIZE);

[And the ability to perform the initialization in that last line isn't
even supported by all platforms still in common use, most notably VC6.]

Or, you can manually stuff values into the container one at a time:

    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(100);
    // ad nauseum...

In the STL Tutorial and Reference Guide, 2nd Edition (Musser et. al.,
2001), a convenience template named "make" is presented on page 22 to
initialize a container of characters from a string literal, one character
at a time. This provides a handy way to illustrate various container
mechanisms and STL algorithms without getting bogged down in the
initialization of the containers...but it only applies to containers of
characters.

I've combined Musser's idea with a technique dating back to 1979 that I
used to initialize arrays in BDS C, my old CP/M C compiler. BDS C didn't
support initialization, so to set an array of ints, I provided a function
initw() that was used like this:

    initw(array, "1,2,3,4,5,100,200");

to parse the values in the string as ints and stuff them into the array.

Based on this hack, I've come up with a fairly straightforward way to
populate any STL (or STL-like) container with an arbitrary list of
values of that container's value_type. I personally needed this
ability more for quick-and-dirty testing of STL facilities than
necessarily for production work, but if memory use isn't a critical
issue this may in fact prove useful in production code as well.

For example, to load up a bunch of arbitrary numeric values into a vector
or deque:

    vector<int> vi = make_cont("1,9,-5,13,22,100,40");
    deque<double> dd = make_cont("2.5, 1.9, -3e50");

Maps and multimaps are supported by writing parenthesized key-value pairs
separated by a delimiter (the intra-pair delimiter defaults to a comma,
but may be specified explicitly in the function call; the inter-pair
comma delimiter may be omitted entirely):

    map<string, int> msi = make_cont("(leor, 10), (lisa, 20),"
                                     "(ray, 30), (katie, 40)");


These forms are not limited to built-in types; in the demo program, you
can see a vector of Widgets being initialized. Any user-defined types will
work provided they have an extractor, and the ability for input values to
be written in an unambiguous comma-delimited format.


Initialization of string values is also supported. A boolean argument
controls whether or not to strip leading spaces from the strings (the
default value is true, to strip the spaces):

             // by default, strip spaces preceding strings
    list<string> ls = make_cont("this, is, a, test");
            // or, supply a final argument of false to retain all spaces:
    deque<string> ds = make_cont("this, is, a, test", false); 


Alternatively, you can specify a numerical sequence by size, initial
value, and increment. The size is required, while the initial value and
increment arguments both have default values of 1:

                        // 100 elements: 50, 53, 56, 59, ...
    vector<int> vi = make_cont(100, 50, 3);   

                        // 100 elements: 20, 21, 22, ...
    deque<long> vl = make_cont(100, 20);

                        // 100 elements: 1, 2, 3, ...
    vector<int>vi = make_cont(100);


You can replace values in existing containers (effectively assigning the
desired values to the containers) using the same choice of formats:

    vector<int> vi; deque<double> dd; list<string> ls;
    // ...
    set_cont(vi, "1,3,3,5");
    set_cont(vd, 100, 50.9, 3.2);
    set_cont(ls, "these, are, now, the, only, strings, in, ls");


You can append/insert values to existing containers (preserving existing
values) using the app_cont variants:

    vector<int> vi; deque<double> dd; list<string> ls;
    // ... put values in all the above containers...
    app_cont(vi, "1,3,3,5");
    app_cont(vd, 100, 50.9, 3.2);
    app_cont(ls, "these, strings, have, been, appended, to, ls");


Finally, the ability to create and reassign containers of pointers is
provided via the make_cont_p and set_cont_p template variations. These
accept a NULL-terminated list of pointers in their parameter list. 

Due to the limitations of using a variable number of parameters, the
use of make_cont_p requires that either the container name appears as
the first argument (as in the first call to make_cont_p below), or
explicit specialization is used in the invocation of the template (as
shown in the second example):

    int i = 10, j = 20, k = 30;
    vector<int *> v = make_cont_p(v, &i, &j, &k, NULL);
    vector<int *> v2 = make_cont_p<vector<int *> >(&i, &j, &k, NULL);

Variations for setting the values of an existing container of
pointers, or appending to an existing container of pointers, are
supplied as set_cont_p and app_cont_p:

    set_cont_p(v2, &k, &j, &i, NULL);
    app_cont_p(v2, &k, &j, &i, NULL);

-- END --


