=================================================== 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 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 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 vi = make_cont("1,9,-5,13,22,100,40"); deque 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 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 ls = make_cont("this, is, a, test"); // or, supply a final argument of false to retain all spaces: deque 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 vi = make_cont(100, 50, 3); // 100 elements: 20, 21, 22, ... deque vl = make_cont(100, 20); // 100 elements: 1, 2, 3, ... vectorvi = 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 vi; deque dd; list 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 vi; deque dd; list 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 v = make_cont_p(v, &i, &j, &k, NULL); vector v2 = make_cont_p >(&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 --