Boost logo

Boost :

From: Sean Hunt (rideau3_at_[hidden])
Date: 2008-03-31 20:21:09


Hi Boosters!

I was wondering if there is any interest for a static initialization
library. The idea I currently have might look something like this:

#include <iostream>
#include <boost/init.hpp>
using namespace boost;
using namespace std;

class myType {
  myType(int i) { cout<<"myType constructed with parameter "<<i<<endl; }
};

void myFunc (int i) {
  cout<<"myFunc called with parameter "<<i<<endl;
}

extern init::variable<myType> myVar (42);
init::function<void (), myVar> myInitFunc (myFunc, 35);
init::variable<myType> myVar;

int main () {
  init::init();
}

The extern declaration of myVar simulates a global defined in a
different translation unit - in this case, function is by the standard
guaranteed to be initialized first, but if myVar is in a different TU,
then the output is undefined. By passing myVar as a parameter to the
function template, the library will ensure that the function is called
after the variable (I was originally considering using a before<myVar>
and after<myVar> syntax, but it would be too difficult to implement an
algorithm that would be guaranteed to get the order right, whereas it's
quite easy like this). The idea would be to allow an easy relationship
for static initialization.

I'm thinking that the variable class should act as a near-transparent
wrapper by overloading all the operators. Since operator . is not
overloadable, I would probably allow it to act through ->, unless the
member is a pointer-like type (the exact definition of pointer-like
could be controlled using template specializations). A member function
would obviously be provided for accessing the object directly (such as
to call a smart pointer's functions). Another idea is to have two
separate classes (say, variable and wrapper), and only one has the
wrapping behavior - the other has to have explicit access each time.

The init function serves as the trigger for all the static
initialization to occur (earlier actual initializations serve only to
add the initializer to the queue) Functors would be provided to defer a
function call (to get a constructor or function parameter) until the
time that the initialization of the object takes place, rather than the
initializer. If an exception is thrown, the initialization library will
remember its state and then a subsequent call would take it off where it
stopped. (adding new objects to the queue once initialization has begun
would be allowable, allowing the initializer to be reused).

Someone will no doubt at some point argue that I should wrap the
functionality in a class to handle the initialization in order for
different code to simultaneously take advantage of the facility, but I
will dismiss that because it would fall prey to static initialization
order and not work as intended. Perhaps later I will add a system that
allows user code to store the current initialization list/state, but I
don't think it would be worth the effort.

One last question: Should I write this using C++09 variadic templates or
the standard boost preprocessor techniques? I think that code written
for variadic templates is more easily convertible to the preprocessor
than vice versa, but I don't know.

Thanks for your comments!

Sean Hunt


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk