[comp.lang.c++] constructors for global objects

davidc@vlsisj.uucp (David Chapman) (06/04/91)

The thread about static object initialization order made me go look
up the discussion in the ARM.  It's a good thing I did, because
I'm doing some things in my code that aren't guaranteed to work!

In particular, I'd like to have self-constructing tables using global
objects.  For example, I could define a file version class.  Its
constructor would get the name of the file (e.g. SCCSid), which it
would then squirrel away, and add itself to the (growing) list of
files.  Then I could define a member function that would traverse
this list, printing all of the versions *without knowing the names
of the objects it is traversing*.  In this way the table extends
itself automatically as I add source code.  As section 3.4 reads now,
only the modules that have had code executed at the time I call the
"print versions" function are guaranteed to have their version
objects constructed.  While this might be useful in telling me
which code has been executed, it's not what I want.

Zortech C++ prints the whole table for me now (which is why I never 
looked up the details in the ARM until now), but obviously I can't 
depend on that unless the language definition is tightened up the 
way I want it.  I don't know how hard it is to do this in cfront (or 
Zortech, or BC++, etc.) but it sure would be nice.

Perhaps locally defined objects not declared "static" could be assured of 
being constructed before main() gains control?  I don't care how it
looks, I just want it to work.

Here's some example code (from memory; I have my actual "working" code
somewhere but I can't find it right now):

// declaration file (filver.hpp):

class fileversion {
    private:
	const char *_ver;
	static fileversion *firstver;
	fileversion *nextver;
    public:
	fileversion(const char *ver);
	printallversions(void);
};

// implementation file (filever.cpp):

#include "filever.hpp"

static fileversion::*firstver;		// implicitly defined as 0; this was
					// the original discussion which made
					// me look this up

fileversion::fileversion(const char *ver)
{
    _ver = ver;
    nextver = firstver;			// here's the self-constructing part!
    firstver = this;			// order of construction not important
}

fileversion::printallversions(void)	// print all file versions
{					// could be fancier, obviously
    fileversion *thisver;

    for (thisver = firstver; thisver != 0; thisver = thisver->nextver)
	printf("%s\n",_ver);
}

// example usage (foo.cpp):

#include "filever.cpp"

fileversion foofilever("File foo.cpp 1-Jun-1991");  // one of these per file

...

// main program (main.cpp):

#include "filever.cpp"

fileversion mainfilever("File main.cpp 3-Jun-1991");

main()
{
    mainfilever.printallversions();	// prints "foo.cpp" and "main.cpp"
}


I have other uses for the self-constructing tables, and they need this
guarantee much more (i.e. holes in the table aren't allowed).  Otherwise,
I'll be forced to put all of the objects into one big file and use "extern"
everywhere else.  :-(

Suggestions?  Comments?

                David Chapman

{known world}!decwrl!vlsisj!davidc
vlsisj!davidc@decwrl.dec.com