This isn't exactly an answer, just a response to a comment that's too long for another comment, and it is relevant to this question.
Please don't use Singleton. Your stated reason for doing so is that you will be using it to store configuration information, and that configuration information needs to be accessible from anywhere in the program.
This is a reason (though, IMHO, not necessarily a great one) for a global variable, but not a reason for a Singleton. What harm is there in more than one object that stores the configuration existing? If all users used a global variable to access it, they would all use the same one. Why is it helpful to forcibly constrain the number of instances to one?
Secondly, what happens in the future when you need to temporarily add some configuration options? Say somehow your program needs to sort of run itself as a sub-program or something with slightly different configuration information, then restore the original configuration? Or maybe you need to frob the configuration in a few different ways for tests and then restore it to its original state? With a Singleton and a global variable this becomes very tricky. But if you used something more flexible, it's pretty trivial.
Now personally, I think passing around the configuration options to all the things that need them in an explicit fashion is not necessarily a bad way to go. But if you think that's intolerable, here's an alternative:
template <typename T>
class DynamicallyScoped {
public:
explicit DynamicallyScoped(T &stackinstance) : oldinstance_(0) {
oldinstance_ = S_curinstance;
S_curinstance = &stackinstance;
}
~DynamicallyScoped() {
S_curinstance = oldinstance_;
oldinstance_ = 0;
}
static T *curInstance() { return S_curinstance; }
private:
static T *S_curinstance;
T *oldinstance_;
// Made private and left undefined on purpose.
DynamicallyScoped(const DynamicallyScoped &b);
const DynamicallyScoped &operator =(const DynamicallyScoped &b);
};
This allows you to replace the current instance for a scope and have it automatically restored when that scope goes away. And it also allows you to say DynamicallyScoped<Foo>::curInstance()->get_something();
anywhere in your program, except in the constructors for static or global objects, and expect to get something useful.
It's a doodle, and probably useful in this form. But I can imagine ways in which it might be better. For example, with some modification you could have several dynamically scoped variables of the same type.
Example usage:
#include <iostream>
template <>
int *DynamicallyScoped<int>::S_curinstance = 0;
extern void doSomething();
extern void doSomethingElse();
extern void printTheInt();
int main(int argc, char *argv[])
{
int x = 5;
DynamicallyScoped<int> theInt(x);
printTheInt();
doSomething();
doSomethingElse();
}
void doSomething()
{
printTheInt();
}
void doSomethingElse()
{
int newint = 6;
DynamicallyScoped<int> subint(newint);
doSomething();
}
void printTheInt()
{
::std::cout << "_The_ integer's value is: "
<< *DynamicallyScoped<int>::curInstance() << '\n';
}
As for the worry that more instances of your 'global config file' object could be created, don't hardcode the filename. Construct the object in main
as a stack variable and give it the filename as an argument. Then there's no problem if other parts of the code create instances of the config file object unless they also give the name of the global configuration file. And if they do that, they deserve what they get.