views:

122

answers:

3

What I want to do: run some prerequisite code whenever instance of the class is going to be used inside a program. This code will check for requiremts etc. and should be run only once.

I found that this can be achieved using another object as static variable inside a constructor. Here's an example for a better picture:

class Prerequisites
{
     public:
         Prerequisites() {
              std::cout << "checking requirements of C, ";
              std::cout << "registering C in dictionary, etc." << std::endl;
         }
};


class C
{
    public:
         C() {
             static Prerequisites prerequisites;
             std::cout << "normal initialization of C object" << std::endl;
         }
};

What bothers me is that I haven't seen similar use of static variables so far. Are there any drawbacks or side-effects or am I missing something? Or maybe there is a better solution? Any suggestions are welcome.

+3  A: 

This isn't thread-safe, since if two threads try to construct C for the first time at the same time, Prerequisites will probably be initialized twice.

If you're okay with that, you can probably do this, though gaming the scoped constructor system has zero discoverability (i.e. once you forget the 'trick' or others try to read your code, they'll be baffled as to what's going on).

Paul Betts
Thanks for advices. Thread safety currently isn't a problem.
doc
+4  A: 

Are there any drawbacks or side-effects or am I missing something? Or maybe there is a better solution? Any suggestions are welcome.

It might be clearer (though more verbose) to explicitly invoke a static method.

class Prerequisites
{
    static bool checkedOnce;    
public:
    static void checkOnce() {
        if (checkedOnce)
        {
            //already checked: don't check again
            return;
        }
        //else check them now
        checkedOnce = true;
        std::cout << "checking requirements of C, ";
        std::cout << "registering C in dictionary, etc." << std::endl;
    }
};

bool Prerequisites::checkedOnce = false;

class C
{
public:
    C() {
        Prerequisites::checkOnce();
        std::cout << "normal initialization of C object" << std::endl;
    }
};
ChrisW
You're maybe right that this is clearer. But what about defining `checkedOnce` boolean as static inside checkOnce()? Less verbosity and still should be clear (?). + atomicity in C++0x.
doc
@doc -- I suggested this more verbose way because it's clearer/more explicit/uses less magic. Could you supply a citation/reference about atomicity of static local variables in C++0x?
ChrisW
I read that here on stackoverflow under following link http://stackoverflow.com/questions/898432/how-is-static-variable-initialization-implemented-by-the-compiler/898603#898603
doc
A: 

You should at least use a mutex and a static flag inside Prerequisites class to protect agains multiple initialization of Prerequisites objects. In that way your code will become thread safe.

Jorg B Jorge
Thread safety isn't a problem here but thanks for advice. BTW I heard that C++0x will make initialization of static variables thread-safe.
doc